构造函数、原型和原型链

114 阅读3分钟

构造函数

什么是构造函数?

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 属性上,而非对象实例本身。

关于原型总结的三个公式:

  1. 对象.__proto__ === 其构造函数.prototype

  2. Object.prototype 是所有对象的(直接或间接)原型

  3. 所有函数都由 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的作用。

  1. 创建一个空对象,作为将要返回的对象的实例。

  2. 将这个空对象的原型,指向构造函数的 prototype 属性。

  3. 将这个空对象赋值给函数内部的 this 关键字。

  4. 开始执行构造函数内部代码。

模拟实现 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;

};

上面代码基本完成,但还可继续优化

构造函数返回值有三种情况:

  1. 返回一个对象
function Dog(color, name) {
    this.color = color;
    return {
        name: name
    }
}

const dog = new Dog("black", "小花");
dog.color;
// undefined

dog.name;
// "小花"

实例 dog 中只能访问到 返回对象中的属性

  1. 没有 return,即返回 undefined
function Dog(color, name) {
    this.color = color;
}

const dog = new Dog("black", "小花");
dog.color;
// 'black'

dog.name;
// undefined

实例 dog 中只能访问到构造函数中的属性,和情况1完全相反。

  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;

};