解析JS的prototype继承机制
2011-04-28 17:17
357 查看
许多人一直对JS的prototype继承机制不明了,到底在创建一个类的实例的时候,解析器为我们做了些什么呢?
首先,我们来看一个例子:
结果将是
firefox “my name” “my name” “my name” “[object object]” undefined
IE “my name” “my name” “my name” undefined 出错
从最后两个结果来看,Firefox下的prototype是可以删除的,但它却是一定会存在的,在做delete(class2.prototype)的时候,Firefox将prototype变成一个普通的Object。
而IE对此的处理方式有所不同,当删除class2.prototype的时候,它就真真正正被删掉了,所以会得到undefined,并且最后一行会出错。
可能就有人会有疑问了,我们都已经把class2.prototype给删除了,虽然Firefox和IE处理方式不同,但确确实实肯定不会存在class2.prototype.name这个变量了,但为什么在删除之后,class2的实例obj的name值会存在?这就是我们要说的重点之一了。
接着看下边几行代码,请使用Firefox来运行。
在我们指定的firefox下运行结果是: “my name” “my name” “my name” “my name” “new name” “my name” “my name” “my name”
是不是觉得结果好奇怪?__proto__这又是什么变量呢?为什么在delete(obj.name)之后,原先这个值为”new name”的属性没消失,但却随着这行代码变成了”my name”
稍加分析,其实这个__proto__对象,就是原先那个class2.prototype,而且尽管class2.prototype被清掉了,这个obj.__proto__对象却依然存在!
我们立刻就可以想到,JS里一个类的实例在实例化完毕之后,就与原先的类的关系断开了。当它在本身找不着一个属性的时候,会尝试去__proto__里找,如果找着就把它当成本身的属性了。
这是根据Firefox提供出来的这个__proto__对象推断出来的,那IE又是怎么样的呢?我们继续看下边简化了的代码:
在看过Firefox下的运行结果后,我们可以很欣喜地看到IE其实处理方式应该是一致的,在删除obj.name之后,它的值确实像Firefox一样,”new name”变成了”my name”,但它并没有给我们提供__proto__这样的对象。
于是,我很肯定但有点武断地得出了以下推论:
在运行”new xxx()”的时候,解析器会创建一个空的Object,然后为它创建了一个名字可能为__proto__(为什么要用可能二字?因为IE不知道起的是什么名,但Firefox确实用了这个名字)的属性,然后将xxx类的prototype赋值给它。接下来,进入类本身,相当于xxx.call(obj)的方式把新的对象当成this一行一行执行下去,然后返回该对象。
从这里也可以看出JS里根本没有类这种东西,或者说没有真正的类,它纯属模拟出来的,这也是为什么类的定义跟函数的定义都用了function这个关键词,事实上类的定义就是一个函数,它负责将传进来的this对象根据函数的逻辑给它增加了属性以及方法,跟其它高级语言里的类的定义是完全不一样的。
欢迎回贴指出我的不足之处,讨论讨论
首先,我们来看一个例子:
function class1() { this.name = "my name"; } function class2() { this.age = 123; } class2.prototype = new class1(); var obj = new class2(); alert(obj.name); alert(class2.prototype.name); delete class2.prototype; alert(obj.name); alert(class2.prototype); alert(class2.prototype.name);
结果将是
firefox “my name” “my name” “my name” “[object object]” undefined
IE “my name” “my name” “my name” undefined 出错
从最后两个结果来看,Firefox下的prototype是可以删除的,但它却是一定会存在的,在做delete(class2.prototype)的时候,Firefox将prototype变成一个普通的Object。
而IE对此的处理方式有所不同,当删除class2.prototype的时候,它就真真正正被删掉了,所以会得到undefined,并且最后一行会出错。
可能就有人会有疑问了,我们都已经把class2.prototype给删除了,虽然Firefox和IE处理方式不同,但确确实实肯定不会存在class2.prototype.name这个变量了,但为什么在删除之后,class2的实例obj的name值会存在?这就是我们要说的重点之一了。
接着看下边几行代码,请使用Firefox来运行。
function class1() { this.name = "my name"; } function class2() { this.age = 123; } class2.prototype = new class1(); var obj = new class2(); alert(obj.name); alert(obj.__proto__.name); delete class2.prototype; alert(obj.name); alert(obj.__proto__.name); obj.name = "new name"; alert(obj.name); alert(obj.__proto__.name); delete obj.name alert(obj.name); alert(obj.__proto__.name);
在我们指定的firefox下运行结果是: “my name” “my name” “my name” “my name” “new name” “my name” “my name” “my name”
是不是觉得结果好奇怪?__proto__这又是什么变量呢?为什么在delete(obj.name)之后,原先这个值为”new name”的属性没消失,但却随着这行代码变成了”my name”
稍加分析,其实这个__proto__对象,就是原先那个class2.prototype,而且尽管class2.prototype被清掉了,这个obj.__proto__对象却依然存在!
我们立刻就可以想到,JS里一个类的实例在实例化完毕之后,就与原先的类的关系断开了。当它在本身找不着一个属性的时候,会尝试去__proto__里找,如果找着就把它当成本身的属性了。
这是根据Firefox提供出来的这个__proto__对象推断出来的,那IE又是怎么样的呢?我们继续看下边简化了的代码:
function class1() { this.name = "my name"; } function class2() { this.age = 123; } class2.prototype = new class1(); var obj = new class2(); alert(obj.name); alert(obj.__proto__); delete class2.prototype; alert(obj.name); obj.name = "new name"; alert(obj.name); delete obj.name alert(obj.name);
在看过Firefox下的运行结果后,我们可以很欣喜地看到IE其实处理方式应该是一致的,在删除obj.name之后,它的值确实像Firefox一样,”new name”变成了”my name”,但它并没有给我们提供__proto__这样的对象。
于是,我很肯定但有点武断地得出了以下推论:
在运行”new xxx()”的时候,解析器会创建一个空的Object,然后为它创建了一个名字可能为__proto__(为什么要用可能二字?因为IE不知道起的是什么名,但Firefox确实用了这个名字)的属性,然后将xxx类的prototype赋值给它。接下来,进入类本身,相当于xxx.call(obj)的方式把新的对象当成this一行一行执行下去,然后返回该对象。
从这里也可以看出JS里根本没有类这种东西,或者说没有真正的类,它纯属模拟出来的,这也是为什么类的定义跟函数的定义都用了function这个关键词,事实上类的定义就是一个函数,它负责将传进来的this对象根据函数的逻辑给它增加了属性以及方法,跟其它高级语言里的类的定义是完全不一样的。
欢迎回贴指出我的不足之处,讨论讨论
相关文章推荐
- cocos2dx 3.0 js继承:John Resiq的继承写法解析
- cocos2dx 3.0 js继承:John Resiq的继承写法解析
- JS中的constructor与prototype(2)--js继承如何实现
- js中继承的几种用法总结(apply,call,prototype)
- JS解析机制
- js 用call或prototype实现类的继承
- 关于js继承---Base类的源码解析
- js中继承的几种用法总结(apply,call,prototype)
- js原型继承机制实例详解
- js继承机制详解
- js继承 prototype和constructor
- JS中继承机制的三种方法
- JavaScript继承机制之prototype, __proto__, constructor
- Vue.js源码解析(九)【从template到DOM(Vue.js源码角度看内部运行机制)】
- js中继承的几种用法总结(apply,call,prototype)
- js继承机制实现
- AngularJS Scope 继承解析
- JS中的constructor与prototype(2)--js继承的实现原理
- JS中的prototype解析
- js中的prototype的解析