Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js构造函数中的疑点 #9

Open
aototo opened this issue Aug 10, 2017 · 0 comments
Open

js构造函数中的疑点 #9

aototo opened this issue Aug 10, 2017 · 0 comments

Comments

@aototo
Copy link
Owner

aototo commented Aug 10, 2017

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

先看下一个例子

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,那就按正常的函数执行。那为什么这里可以这么使用?

我们先看下new的原理

(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。

(3)第三步就是执行Book函数,并且让this指向myBook对象

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

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

例子:

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

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

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

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

function Book() {
    return new Number();
}
...

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

Note: 使用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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant