对象的构造
字面量方式
使用对象字面量形式是一种常见的构造对象的方式,不再多说。如下:1
2
3
4
5
6
7
8
9
10
11
12var person = {
name: 'Julia',
age: 23,
address: {
prov: 'Zhejiang',
city: 'hangzhou'
},
'test attr': 1, //当属性名不是有效标识符时,需要给属性名加上''
sayHi: function(name) {
console.log(`Hi, ${name}, I'm ${this.name}`);
}
};
构造器方式
类似于 Java 中使用构造器进行对象构造的形式,JS 中也可以用构造器的方式来构造对象。如下:1
2
3
4
5
6
7
8
9
10function Person(name, age, address, test) {
this.name = name;
this.age = age;
this.address = address;
this['test attr'] = test;
}
Person.prototype.sayHi = function(name) {
console.log(`Hi ${name}, I'm ${this.name}`);
}
var person = new Person('Julia', 23, { prov: 'Zhejiang', city: 'hangzhou' }, 1);
这是常用的一种构造对象的方式,它组合了构造器的方式和原型的方式。构造器主要用于构造对象自身有的属性,比如本例中的姓名、年龄等;原型方式主要用于构造对象之间公有的特征,比如 sayHi 方法。最后,通过 new 操作符构造出了 Person,以这种方式调用构造函数实际会经历如下四个步骤:
- 创建一个新对象
- 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象)
- 执行构造函数中的代码(为这个新对象添加属性)
- 返回新对象
Object.create 方法
使用这种方法可以为你要创建的对象指定其原型,而不用定义一个构造函数。如下:1
2
3
4
5
6
7
8
9
10
11
12
13var person = {
name: 'Julia',
age: 23,
address: {
prov: 'Zhejiang',
city: 'hangzhou'
},
'test attr': 1, //当属性名不是有效标识符时,需要给属性名加上''
sayHi: function(name) {
console.log(`Hi, ${name}, I'm ${this.name}`);
}
};
var person1 = Object.create(person);
以上代码构造了一个 person1 对象,它是以 person 对象作为其原型的。换言之,如果我使用 Object.create(person) 构造了 person2,person3…很多个对象,它们都会拥有 person 对象上的所有属性和方法。
原型与原型属性
原型指的是 prototype,原型属性指的是 __proto__。偶然看到过的一句话,我觉得可以深刻地解释它们分别是什么:prototype 代表胚胎,__proto__ 代表父亲。这句话很值得挖掘。先说 prototype,它代表的是胚胎,意味着它是可以用来产生新的对象的,可以不基于已有对象,并且用来产生新对象的方法是通过使用函数,所以 prototype 属性是函数才有的(这是个人看法,这样理解会变得十分简单)。而所有的对象都有父亲,所以每个对象都有 __proto__ 属性。为了更清楚的理解这两个属性,这里结合以上三种构造对象的方式来进行解释。
字面量方式
1 | var a = {}; |
构造器方式
1 | var A = function() {}; |
Object.create 方法
1 | var a1 = {}; |
原型链
原型链是 JS 中实现继承的主要方式。原型链这个词中的原型二字,指的实际上是 __proto__ 属性而非 prototype 属性。可以这么理解,JS 中万物皆对象,而 __proto__ 是所有对象都有的属性,prototype 只是函数才有的属性,所以 prototype 是无法形成链条的,而 __proto__ 是可以做到的。下面一张图,可以清楚地展示出原型链。1
2var A = function() {};
var a = new A();
从这张图我们可以看出一条由 __proto__ 链起来的链条,这就是原型链。在 JS 中,Object 是所有对象的基类,这一点我们也可以从图中观察到,null 总是位于原型链的顶端,Object 仅次于 null。当 JS 引擎查找属性时,会先查找对象本身是否存在该属性,如果不存在,会在原型链上查找,直至回溯到原型链的顶端。