回顾Javascript构造函数

长期更新文章 喜欢的start下 github.com/aototo/blogjavascript

构造函数已是老生常谈的事情了。这里讲一些比较基础的东西。java

先看下一个例子git

function Book(name) { 
    if (!(this instanceof Book)) { 
        // the constructor was called without "new".
        return new Book(name);
    } 
}

var myBook = Book(name);
var myBook1 = Book(name);
myBook.constructor === myBook1.constructor // true复制代码

首先判断this是否为Book的实例,不是就返回新的实例。常常用于解决在构造函数前面忘记使用new的状况,若是没有使用在function前面使用new,那就按正常的函数执行。那为何这里能够这么使用?github

咱们先看下new的原理bash

(1) 建立一个新的对象: var myBook = New Object()
(2) 设置对象的__proto__ 指向构造函数的prototype
    myBook.__proto__ = Book.prototype复制代码

到了第二步骤咱们就能够看到myBook能够访问构造函数的prototype的constructor。函数

var myBook = New Object();
myBook.__proto__ = Book.prototype;
myBook instanceof Book // true复制代码

当执行第二步骤之后例子中的 if (!(this instanceof Book)) 就不会被执行。因此this instanceof Book能够判断当前函数是否使用new。从而避免开发者忽略而形成程序错误的状况。ui

(3)第三步就是执行Book函数,而且让this指向myBook对象复制代码

第四步就是判断Book返回值的类型:this

判断条件
(1)若是是值类型就丢弃,返回instance。
(2)若是是引用类型,就返回这个引用类型的对象,替换掉instance。复制代码

例子:spa

function Book() {
    return 2;
}
var myBook = new Book();
myBook instanceof Book // true复制代码

return 2属于值类型,包括String、布尔值、null、undefined等..若是是值类型,就丢弃返回instance。prototype

function Book() {
    var newObj = {}
    return newObj;
}
var myBook = new Book();
myBook instanceof Book // false复制代码

若是是引用类型,就返回这个引用类型的对象

function Book() {
    return new Number();
}
...复制代码

若是return的值是一个Number 对象,那么实例对象的值就是Number 对象。

使用Object.create()建立的对象其proto 并非指向构造函数。

原型链继承须要注意的一点

例子:

function Car() {}
function Bmw() {}

Bmw.prototype = new Car();
Bmw.prototype.constructor = Bmw; 

var bmw1 = new Bmw();复制代码

比较奇怪的是 Bmw.prototype.constructor = Bmw; 解释下为何要这么处理。
假设若是没有这行

bmw1.constructor === Car //true复制代码

Bmw.prototype 其实是 new Car() 的实例,结果致使Bmw prototype中的 constructor从丢失(ps: function建立后prototype已经有constructor值),
bmw1对象在原型链中查询constructor的时候指向了构造函数Car,这明显是错误的。所以这里修正了Bmw.prototype.constructor = Bmw。同时还能够经过proto获取Car的构造函数。

bmw1.__proto__.__proto__.constructor === Car复制代码
相关文章
相关标签/搜索