javascript instanceof 内部机制探析_Javascript教程-查字典教程网
javascript instanceof 内部机制探析
javascript instanceof 内部机制探析
发布时间:2016-12-30 来源:查字典编辑
摘要:比如:复制代码代码如下://代码1functionPig(){}varpig=newPig();alert(piginstanceofPig...

比如:

复制代码 代码如下:

// 代码 1

function Pig() {}

var pig = new Pig();

alert(pig instanceof Pig); // => true

function FlyPig() {}

FlyPig.prototype = new Pig();

var flyPig = new FlyPig();

alert(flyPig instanceof Pig); // => true

来看另一段代码:

复制代码 代码如下:

// 代码 2

function Pig() { Pig.prototype = {/* some code */} }

var pig = new Pig();

alert(pig instanceof Pig); // => false

为何上面的猪 pig 不再是猪 Pig 了呢?

当一个对象是某个类的实例时,意味着这个对象具有该类的方法和属性。在 JavaScript 中,一个猪类的特性体现在原型中:

复制代码 代码如下:

// 代码 3

function Pig() {}

Pig.prototype = {

"吃猪食": function() {},

"睡觉": function() {},

"长膘": function() {}

};

var pig = new Pig();

alert(pig instanceof Pig); //=> true

如果动态改变了猪的特性,让猪变成了牛:

复制代码 代码如下:

// 代码 4

Pig.prototype = {

"吃草": function() {},

"犁田": function() {}

};

var niu= new Pig();

alert(pig instanceof Pig); //=> false

alert(niu instanceof Pig); //=> true

当未改变 Pig 的 prototype 时,猪还是猪,因此代码 3 中 pig 是 Pig 的实例。当改变 prototype 后,猪已经不是猪,而是披着猪皮的牛了。因此代码 4 中 pig 不再是 Pig 的实例,niu 反而是 Pig 的实例。

进一步分析前,先回顾一下 new 的内部机制。代码 2 中的 new Pig() 实际上等价为:

复制代码 代码如下:

// var pig = new Pig() 的等价伪代码:

var pig = (function() {

var o = {};

o.__proto__ = Pig.prototype; // line 2

Pig.call(o);

Pig.prototype = {/* some code */}; // line 4

return o; // line 5

})();

可以看出,在 line 2 时,o.__proto__ 指向了 Pig.prototype 指向的值。但在 line 4 时,Pig.prototype 指向了新值。也就是说,在 line 5 返回时,pig.__proto__ !== Pig.prototype. 正是这个变化,导致了代码 2 中的 pig 不是 Pig.

已经可以大胆推论出:instanceof 判断 pig 是不是 Pig 的依据是:看隐藏的 pig.__proto__ 属性是否等于 Pig.prototype !

为了进一步确认,我们可以在 Firefox 下模拟 instanceof 的内部实现代码:

复制代码 代码如下:

/**

* Gecko 引擎下,模拟 instanceof

*/

function _instanceof(obj, cls) {

// instanceof 的左操作数必须是非null对象或函数对象

if((typeof obj !== "object" || obj === null)

&& typeof obj !== "function") {

return false;

}

// instanceof 的右操作数必须是函数对象

if(typeof cls !== "function") {

throw new Error("invalid instanceof operand (" + cls + ")");

}

// 向上回溯判断

var p = obj.__proto__, cp = cls.prototype;

while(p) {

if(p === cp) return true;

p = p.__proto__;

}

return false;

}

测试页面:simulate-intanceof.html

最后考考大家:

复制代码 代码如下:

function Bird() {}

var bird = new Bird();

var o = {};

bird.__proto__ = o;

Bird.prototype = o;

alert(bird instanceof Bird); // true or false?

相关阅读
推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
  • 大家都在看
  • 小编推荐
  • 猜你喜欢
  • 最新Javascript教程学习
    热门Javascript教程学习
    编程开发子分类