通过构造函数创建对象
前面讲过,创建对象主要有两种方式,一种是通过字面量的方式来创建对象,另一种是通过构造函数的方式。这里我们讲一下通过构造函数创建对象
构造函数并不是一种特殊的函数,而是使用 new
关键字调用普通函数则叫构造函数,
构造函数操作逻辑
使用 new
调用构造函数的操作逻辑如下:
- 在内存中创建一个新对象
- 这个新对象内部的[[Prototype]]特性被赋值为构造函数的
prototype
属性 - 构造哈数内部的
this
被赋值为这个新对象(即this
指向新对象) - 执行构造函数内部的代码(给新对象添加属性)
- 如果构造函数返回非空对象,则返回该对象,否则,返回刚创建的新对象
例子
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log('我的名字叫: ' + this.name);
}
var a = new Person('knight');
a;
a.sayName();
在上面的的例子中,我们声明了一个 Person()
,并在其原型上添加 sayName()
, 然后通过 new
实例化对象并赋值给 a
。
我们之所以将 sayName()
添加在 Person
的原型上,是为了重用这个方法
继承
JavaScript 中继承主要是通过原型链来实现的,其基本思想是通过原型继承多个引用类型的属性和方法。
组合继承
组合继承的基本思路是使用原型链继承原型上的属性和方法,而通过调用父类构造函数继承实例属性。
function SuperType(name) {
this.name = name;
}
SuperType.prototype.sayName = function () {
console.log('我的名字叫: ' + this.name);
}
function SubType(name, age) {
SuperType.call(this, name)
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function () {
console.log('我的年龄是: ' + this.age);
}
var a = new SubType('knigt', 18);
a;
a.sayName();
a.sayAge();
但是这种方式的主要问题是实例化了两次父类,造成了效率问题,并且原型因为是实例化的父类,所以有多余的属性。
寄生式继承
寄生式继承背后的思路类似于寄生构造器函数和工厂模式:创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象。
function createAnother(obj) {
let clone = Object.create(obj);
clone.sayHi = function () {
console.log('Hi');
}
return clone
}
let obj = {
name: 'knight',
}
var a = createAnother(obj);
a;
a.sayHi();
这种方式适合主要关注对象,不在乎类型和构造函数的场景,且在工厂方法中给对对象添加方法使工厂函数难以复用。
寄生式组合继承
寄生式组合继承糅合了寄生式继承和组合式继承的优点,
function inheritPrototype(subType, superType) {
let prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
function SuperType(name) {
this.name = name;
}
SuperType.prototype.sayName = function () {
console.log('我的名字叫: ' + this.name);
}
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function () {
console.log('我的年龄是: ' + this.age);
}
var a = new SubType('knigt', 18);
a;
a.sayName();
a.sayAge();
Object.create()
Object.create()
可传入两个参数,第一个参数作为新对象原型的对象,第二个参数传入属性描述符,给新对象定义额外属性的对象(第二个可选)
function SuperType(name) {
this.name = name;
}
var obj = new SuperType('knight');
var a = Object.create(obj, {age: {value: 18}});
a;