构造函数
什么是构造函数?
constructor
返回实例对象时构造函数的引用。此属性的值是对函数本身的引用,而不是一个包含函数名称的字符串。
function Dog(color){
this.color = color
}
const dog = new Dog('red')
dog.constructor === Dog // true
构造函数本身就是一个函数,与普通函数没有任何区别,不过为了规范一般将其首字母大写。构造函数和普通函数的区别在于,使用 new 生成实例的函数就是构造函数,直接调用的就是普通函数。
普通函数创建的实例的 constructor
属性是?
function Dog(color){
return {color: color}
}
const dog2 = Dog('blue')
dog2.constructor === Object // true
原型
每个对象拥有一个原型对象,对象以其原型为模板,从原型继承方法和属性,这些属性和方法定义在对象的构造器函数的 prototype
属性上,而非对象实例本身。
关于原型总结的三个公式:
-
对象.__proto__ === 其构造函数.prototype
-
Object.prototype 是所有对象的(直接或间接)原型
-
所有函数都由 Function 构造。
原型链
每个实例对象( object
)都有一个私有属性(称之为 __proto__
)指向它的构造函数的原型对象(prototype
)。该原型对象也有一个自己的原型对象( __proto__
) ,层层向上直到一个对象的原型对象为 null
。这种关系被称为原型链 (prototype chain)。
function Dog(color) {
this.color = color
}
const dog3 = new Dog('green')
dog3.__proto__ === Dog.prototype // true
dog3.__proto__.__proto__ === Object.prototype // true
dog3.__proto__.__proto__.__proto__ === null // true
关于通过构造函数实例化对象时, new的作用。
-
创建一个空对象,作为将要返回的对象的实例。
-
将这个空对象的原型,指向构造函数的
prototype
属性。 -
将这个空对象赋值给函数内部的
this
关键字。 -
开始执行构造函数内部代码。
模拟实现 new
function create() {
// 创建一个空对象
var obj = new Object(),
// 获得传入的构造函数(arguments中去除第一个参数可得到)
Constructor = [].shift.call(arguments);
// 链接到原型,obj 可以访问到构造函数原型中的属性
obj.__proto__ = Constructor.prototype;
// // 绑定 this 实现继承,obj 可以访问到构造函数中的属性
Constructor.apply(obj, arguments);
// 返回对象
return obj;
};
上面代码基本完成,但还可继续优化
构造函数返回值有三种情况:
- 返回一个对象
function Dog(color, name) {
this.color = color;
return {
name: name
}
}
const dog = new Dog("black", "小花");
dog.color;
// undefined
dog.name;
// "小花"
实例
dog
中只能访问到 返回对象中的属性
- 没有
return
,即返回undefined
function Dog(color, name) {
this.color = color;
}
const dog = new Dog("black", "小花");
dog.color;
// 'black'
dog.name;
// undefined
实例
dog
中只能访问到构造函数中的属性,和情况1完全相反。
- 返回
undefined
以外的基本类型
function Dog(color, name) {
this.color = color;
return 'i miss you'
}
const dog = new Dog("black", "小花");
dog.color;
// 'black'
dog.name;
// undefined
实例
dog
中只能访问到构造函数中的属性,结构相当于没有返回值。
所以我们还需要判断返回的值是不是一个对象,如果是一个对象,我们就返回这个对象,要么就返回新创建的 obj
对象。
所以优化代码:
function create() {
var obj = new Object(),
Constructor = [].shift.call(arguments);
obj.__proto__ = Constructor.prototype;
const result = Constructor.apply(obj, arguments);
return result instanceof Object ? result : obj;
};