`

解析JS的prototype继承机制

    博客分类:
  • js
阅读更多

许多人一直对JS的prototype继承机制不明了,到底在创建一个类的实例的时候,解析器为我们做了些什么呢?
首先,我们来看一个例子:

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对象根据函数的逻辑给它增加了属性以及方法,跟其它高级语言里的类的定义是完全不一样的。

 

原文:http://bbs.51js.com/thread-83874-1-1.html

分享到:
评论

相关推荐

    javascript关于继承解析

    上一篇已介绍了组合继承,现在讲讲剩余的几种继承。 原型式继承 调用一个函数,接收这个函数返回来的对象,这个对象的原型就是传入函数的参数对象。 如: function personObject(o){ function F(){} F.prototype ...

    Javascript组合继承方法代码实例解析

    组合继承 组合继承,指将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其背后思路使用用原型链实现对原型属性和方法的...SuperType.prototype.sayName = function() { console.log(this.

    js原型链与继承解析(初体验)

    首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在。...

    戏说JS中的原型-Prototype

    什么是原型:在了解原型链之前我们先来看看一个函数在创建过程中做了哪些事情,举一个空函数的例子:当我们在代码里面声明这么一个空函数,js解析的本质是:1、创建一个对象(有constructor属性及[[Prototype]]属性...

    JavaScript原型和继承

    前几天看了《再谈js面向对象编程》,当时就请教...当我们在代码里面声明这么一个空函数,js解析的本质是(肤浅理解有待深入):1、创建一个对象(有constructor属性及[[Prototype]]属性),根据ECMA,其中[[Prototype]

    javaScript中的原型解析【推荐】

    最近在学习javaScript,学习到js面向对象中的原型时,感悟颇多。若有不对的地方,希望可以指正。 js作为一门面向对象的语言,自然也拥有了继承这一概念,但js中没有类的概念,也就没有了类似于java中的extends,所以...

    JavaScript中原型链存在的问题解析

    我们知道使用原型链实现继承是一个goodway:)看个原型链继承的例子。 function A () { this.abc = 44; } A.prototype.getAbc = function (){ return this.abc; }; function B() { } B.prototype = new A(); // B...

    js对象实例详解(JavaScript对象深度剖析,深度理解js对象)

    JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕。 平时发的文章基本都是开发中遇到的问题和对最佳解决方案的探讨,终于忍不住要写一篇基础概念类的文章了。 本文探讨...

    解析John Resig Simple JavaScript Inheritance代码

     John Resig 写了一篇关于 JavaScript 里 类似其它语言的 “继承”, 灵感来自于 base2 and PrototypeJS. 他为文章起名为”Simple JavaScript Inheritance” . 他使用的一些很巧妙的技术来实现 super 方法. 你还...

    javascript学习笔记.docx

    f) 继承:只是在查询一个属性时自动发生,而不会在写属性时发生,就是说单写一个父类的属性时,JavaScript环境会为对象本身创建一个同名的属性,从此该属性就覆盖了父类中的属性。 12) 创建一个数组可用 new Array()...

    Ajax完全自学手册(PPT)

    第5章 JavaScript中的继承 Test4OO.htm 什么是对象 Test4OO.htm 对象分类 TestStatic.htm 作用域、静态作用域、this关键字 Test4Factory.htm 工厂方式 test4Constract.htm 构造函数 Test4Fixed.htm ...

    Java版水果管理系统源码-website-collection:开发者的网址收藏

    JavaScript实用库,提供了类似Prototype.js的一些功能,但是没有继承任何JavaScript内置对象。 : 一个 JavaScript 日期处理类库,用于解析、检验、操作、以及显示日期。 : 一个 JavaScript 实用工具库,提供一致性,模块...

    Ajax完全自学手册PPT和源代码(ptt格式)

    第5章 JavaScript中的继承 Test4OO.htm 什么是对象 Test4OO.htm 对象分类 TestStatic.htm 作用域、静态作用域、this关键字 Test4Factory.htm 工厂方式 test4Constract.htm 构造函数 Test4Fixed.htm 混合方式 dynamic...

    Ajax完全自学手册(源代码).rar

    第5章 JavaScript中的继承 Test4OO.htm 什么是对象 Test4OO.htm 对象分类 TestStatic.htm 作用域、静态作用域、this关键字 Test4Factory.htm 工厂方式 test4Constract.htm 构造函数 Test4Fixed.htm ...

    千方百计笔试题大全

    44、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类?是否可以implements(实现)interface(接口)? 12 45、内部类可以引用他包含类的成员吗?有没有什么限制? 12 46、java 中实现多态的机制是什么...

    java面试宝典

    203、编程用JAVA解析XML的方式. 49 204、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? 51 205、EJB与JAVA BEAN的区别? 51 206、EJB的基本架构 51 207、MVC的各个部分都有那些技术来实现?如何实现? 52...

    Ajax基础教程(扫描版)

    5.7.1 通过prototype属性建立面向对象的javascript 142 5.7.2 私有属性和使用javascript的信息隐藏 146 5.7.3 javascript中基于类的继承 148 5.7.4 汇合 149 5.8 小结 152 第6章 使用jsunit测试javascript代码 ...

    精通Qt4编程(第二版)源代码

    \19.4 基于Prototype的继承 467 \19.5 小结 467 \第20章 国际化 468 \20.1 Unicode与字符编码 468 \20.1.1 Unicode 468 \20.1.2 汉字编码 469 \20.1.3 编码转换 469 \20.2 Qt Linguist 471 \20.2.1 发布管理...

    精通qt4编程(源代码)

    \19.4 基于Prototype的继承 467 \19.5 小结 467 \第20章 国际化 468 \20.1 Unicode与字符编码 468 \20.1.1 Unicode 468 \20.1.2 汉字编码 469 \20.1.3 编码转换 469 \20.2 Qt Linguist 471 \20.2.1 发布管理器 472 \...

    正则表达式

    尾部的数字,那么如果我们将模式的数字部分放在括号中 (/ [a-z] + (\d+)/) ,我们就可以从所检索到的任何匹配中抽取数字了,之后我们会对此进行解析的. 代括号的子表达式的另一个用途是,允许我们在同一正则表达式的...

Global site tag (gtag.js) - Google Analytics