对象的方法补充
- hasOwnProperty
- 对象是否有某一个属于自己的属性(不是在原型上的属性)
- in/for in 操作符
- instanceof
- 用于检测构造函数(Person、Student类)的pototype,是否出现在某个实例对象的原型链上
- isPrototypeOf
- 用于检测某个对象,是否出现在某个实例对象的原型链上
class定义类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Person {
}
var p1 = new Person() var p2 = new Person() console.log(p1, p2)
var Student = class {
} var foo = function() {
}
var stu1 = new Student() console.log(stu1)
|
类和构造函数的异同
- 我们来研究一下类的一些特性:
- 你会发现它和我们的构造函数的特性其实是一致的;
类的构造函数
- 如果我们希望在创建对象的时候给类传递一些参数,这个时候应该如何做呢?
- 每个类都可以有一个自己的构造函数(方法),这个方法的名称是固定的constructor;
- 当我们通过new操作符,操作一个类的时候会调用这个类的构造函数constructor;
- 每个类只能有一个构造函数,如果包含多个构造函数,那么会抛出异常;
- 当我们通过new关键字操作类的时候,会调用这个constructor函数,并且执行如下操作:
- 1.在内存中创建一个新的对象(空对象);
- 2.这个对象内部的[[prototype]]属性会被赋值为该类的prototype属性;
- 3.构造函数内部的this,会指向创建出来的新对象;
- 4.执行构造函数的内部代码(函数体代码);
- 5.如果构造函数没有返回非空对象,则返回创建出来的新对象;
类的实例方法
- 在上面我们定义的属性都是直接放到了this上,也就意味着它是放到了创建出来的新对象中:
- 在前面我们说过对于实例的方法,我们是希望放到原型上的,这样可以被多个实例来共享;
- 这个时候我们可以直接在类中定义;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class Person { constructor(name, age) { this.name = name this.age = age }
running () { console.log(this.name + " running~") } eating () { console.log(this.name + " eating~") } }
var p1 = new Person("why", 18)
console.log(p1.name, p1.age) p1.running() p1.eating()
console.log(Person.prototype === p1.__proto__) console.log(Person.running) console.log(Person.prototype.running)
|
类的访问器方法
我们之前讲对象的属性描述符时有讲过对象可以添加setter和getter函数的,那么类也是可以的
类的静态方法
静态方法通常用于定义直接使用类来执行的方法,不需要有类的实例,使用static关键字来定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| var names = ["abc", "cba", "nba", "mba"] class Person { constructor(name, age) { this.name = name this.age = age }
running () { console.log(this.name + " running~") } eating () { }
static randomPerson () { console.log(this) var randomName = names[Math.floor(Math.random() * names.length)] return new this(randomName, Math.floor(Math.random() * 100)) } }
var p1 = new Person() p1.running() p1.eating() var randomPerson = Person.randomPerson() console.log(randomPerson)
|
ES6类的继承 - extends
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Person { constructor(name, age) { this.name = name this.age = age }
running () { console.log(this.name, " ex-running~") } eating () { console.log(this.name, " ex-eating~") }
}
class Student extends Person { constructor(name, age, sno, score) { super(name, age) this.sno = sno this.score = score } studying () { console.log(this.name, " my-studying~") } }
var stu1 = new Student("why", 18, 111, 100) stu1.running() stu1.eating() stu1.studying()
|
super关键字
- 我们会发现在上面的代码中我使用了一个super关键字,这个super关键字有不同的使用方式:
- 注意:在子(派生)类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数!
- super的使用位置有三个:子类的构造函数、实例方法、静态方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| class Animal { running () { console.log("ex-running") } eating () { console.log("ex-eating") }
static sleep () { console.log("static animal sleep") } }
class Dog extends Animal { running () { console.log("dog四条腿") super.running() }
static sleep () { console.log("趴着") super.sleep() } }
var dog = new Dog() dog.running() dog.eating()
Dog.sleep()
|
继承内置类
我们也可以让我们的类继承自内置类,比如Array:
类的混入mixin
- JavaScript的类只支持单继承:也就是只能有一个父类
- 那么在开发中我们我们需要在一个类中添加更多相似的功能时,应该如何来做呢?
- 这个时候我们可以使用混入(mixin);
JavaScript中的多态
- 面向对象的三大特性:封装、继承、多态。
- 前面两个我们都已经详细解析过了,接下来我们讨论一下JavaScript的多态。
- JavaScript有多态吗?
- 个人的总结:不同的数据类型进行同一个操作,表现出不同的行为,就是多态的体现。
- 那么从上面的定义来看,JavaScript是一定存在多态的。
字面量的增强
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
var name = "why" var age = 18
var key = "address" + " city"
var obj = { name, age,
running: function() { console.log(this) }, swimming() { console.log(this) }, eating: () => { console.log(this) },
[key]: "广州" }
obj.running() obj.swimming() obj.eating()
function foo() { var message = "Hello World" var info = "my name is why"
return { message, info } }
var result = foo() console.log(result.message, result.info)
|
解构
- ES6中新增了一个从数组或对象中方便获取数据的方法,称之为解构Destructuring。
- 解构赋值 是一种特殊的语法,它使我们可以将数组或对象“拆包”至一系列变量中。
- 我们可以划分为:数组的解构和对象的解构。
- 数组的解构:
- 基本解构过程
- 顺序解构
- 解构出数组:…语法
- 默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var names = ["abc", "cba", undefined, "nba", "mba"]
var [name1, name2, name3] = names console.log(name1, name2, name3)
var [name1, , name3] = names console.log(name1, name3)
var [name1, name2, ...newNames] = names console.log(name1, name2, newNames)
var [name1, name2, name3 = "default"] = names console.log(name1, name2, name3)
|
- 对象的解构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| var obj = { name: "why", age: 18, height: 1.88 } var { name, age, height } = obj console.log(name, age, height)
var { height, name, age } = obj console.log(name, age, height)
var { height: wHeight, name: wName, age: wAge } = obj console.log(wName, wAge, wHeight)
var { height: wHeight, name: wName, age: wAge, address: wAddress = "中国" } = obj console.log(wName, wAge, wHeight, wAddress)
var { name, age, ...newObj } = obj console.log(newObj)
function getPosition ({ x, y }) { console.log(x, y) }
getPosition({ x: 10, y: 20 }) getPosition({ x: 25, y: 35 })
function foo (num) { }
foo(123)
|