翻译一段JS权威指南上的话,顺带转一下一些关于JS面向对象的内容
2010-08-17 09:17
447 查看
Theprototypepropertyisusedwhenafunctionisusedasaconstructor.Itreferstoanobjectthatservesastheprototypeforanentireclassofobjects.Anyobjectcreatedbytheconstructorinheritsallpropertiesoftheobjectreferredtobytheprototypeproperty.
大意是:prototype属性一般在一个函数被用来当作构造函数时候使用,它引用了一个充当整个“类”(函数)prototype的对象,只要由这个构造函数创建的对象都继承被prototype属性引用对象的全部属性。
下面讲讲JS的基于原型的“面向对象”机制
JavaScript是一个基于原型的面向对象语言,每一个对象都有一个原型,Javascript的继承机制是通过模拟Java来实现的,并非真正严格意义上的继承,被继承的对象(Java中称为父类或超类)称为继承对象的原型,JavaScript中的所有的对象(包括自定义的对象)都有原型,没有指定原型的对象其原型默认为Object,Object是所有对象原型的根,Object中有prototype、constructor两个属性及hasOwnproperty(property)、isprototypeOf(Object)toString(),valueOf()等方法函数,这就意味着所有的对象(包括自定义的对象)都有这些属性及方法。
(以下为转)
首先说类,要声明的是,至少到目前为止Javascript中没有类,所谓的“类”其实不是真正的类,它只是表现的像其他面向对象的语言中的类而已,它的本质是函数+原型对象(prototype)。有人说javascript也是面向对象的,只是它是prototypebased,当然这只是概念上的区别,我不想讨论js是不是面向对象的,关键是想说明虽然javascript的类表现得很像其他语言中的类,但是内部的实现机理确不太一致,如果一味的把javascript中的类类比作其他语言中的类,有时候脑子会犯混。
先看一段简单的代码,一般教材上介绍如何新建一个类的时候都是这样的(当然还有更复杂的方法,不过本质上是一样的):
毫无疑问,此时obj具有一个x属性,现在的值是Helloclass.但是,obj到底是什么?MyClass仅仅是一个函数而已,我们称之为构造函数。在其他OO的语言中,构造函数是要放在class关键字内部的,也就是先要声明一个类。另外,函数体内的this又是什么?其他OO语言中,this的概念是很明确的,就是当前对象,因为它在构造函数执行之前已经声明了类,类的内部的一些字段都是已经定义好的。
先解释下,在javascript的函数中,this关键字表示的是调用该函数的作用域(scope),作用域的概念也不是太好理解,下面再解释。不过可以简单的认为它是调用函数的对象。再看MyClass函数,它内部的this是什么呢?
如果我们把代码改成:
varobj=MyClass('Helloclass');
这是完全合乎语法的。如果这段代码是在浏览器中运行的,调试一下可以发现,this是window对象。而和obj没有任何关系,obj还是undefined,alert也不会有结果。原来的代码之所以可以工作,都是new关键字的功劳。new关键字把一个普通的函数变成了构造函数。也就是说,MyClass还是一个普通的函数,它之所以能构造出一个obj,基本上是new的功劳。当函数之前有new关键字的时候,javascript会创造一个匿名对象,并且把当前函数的作用域设置为这个匿名对象。然后在那个函数内部引用this的话就是引用的这个匿名对象,最后,即使这个函数没有return,它也会把这个匿名对象返回出去。那么obj自然就具有了x属性。
现在这个MyClass已经有点像一个类了。但是,这并不是new的工作的全部。Javascript同样可以方便的实现继承——依靠是prototype.prototype也是一个对象,毕竟除了原始类型,所有的东西都是对象,包括函数。更为重要的是,前面提到javascript是prototypebased,它的含义就是在javascript中没有类的概念,类是不存在的,一个函数,它之所以表现的像类,就是靠的prototype.prototype可以有各种属性,也包括函数。上一段说的new在构造对象的过程中,在最终返回那个匿名对象之前,还会把那个函数的prototype中的属性一一复制给这个对象。这里的复制是复制的引用,而不是新建的一个对象,把内容复制过来,在其内部,相当于保留了一个构造它的函数的prototype的引用。有些教材含糊的说所有的“所有对象都有一个prototype属性”,这种说法是不确切的,虽然它内部确实有一个prototype属性,但是对外是不可见的。只有函数对象是有prototype属性的,函数对象的prototype默认有一个constructor属性。
看如下的代码:
输出的结果是changed和ChangedToo。此代码说明了对象内部保留的是构造函数的prototype的引用,要注意的是,proObj中也是保留的它的构造函数的prototype的引用。如果把代码改成:
输出的就是Iamwinner和ChangedToo了。事实上,这些prototype逐层引用,构成了一个prototype链。当读取一个对象的属性的时候,首先寻找自己定义的属性,如果没有,就逐层向内部隐含的prototype属性寻找。但是在写属性的时候,就会把它的引用覆盖掉,是不会影响prototype的值的。
再介绍闭包,首先说明下,这里的闭包(closure)和离散数学中关系的传递闭包中的不是一个概念,我曾以为他们之间有关联,后来仔细想想,似乎并无什么关联,恰好名字一样而已。先看定义:
Closure
A"closure"isanexpression(typicallyafunction)thatcanhavefreevariablestogetherwithanenvironmentthatbindsthosevariables(that"closes"theexpression).
要完全理解闭包需要对Javascript函数的机理有比较透彻的理解,而这个机理有点复杂,并不是三言两语能讲清的,即使是这篇文章,也只是大概讲了下原理。大意就是任何一个函数调用都在一个运行上下文(ExecutionContext)中执行的,这个上下文中有一个作用域对象,其中包括了这个函数的局部变量、参数等。另外,如果一个函数是一个内部函数,它的作用域中含有它外部函数的作用域。在内部函数遇到一个变量名的时候,它是从内部的作用域找起,不断往外层的作用域找。因此,如果内部函数作为一个对象返回出外部函数的时候,即使外部函数已经执行完毕,但是由于其内部函数仍有引用指向它,内部函数不会被释放,因为内部函数有外部函数的作用域,因此外部函数的局部变量也不会被释放。这就构成了闭包。
大意是:prototype属性一般在一个函数被用来当作构造函数时候使用,它引用了一个充当整个“类”(函数)prototype的对象,只要由这个构造函数创建的对象都继承被prototype属性引用对象的全部属性。
下面讲讲JS的基于原型的“面向对象”机制
JavaScript是一个基于原型的面向对象语言,每一个对象都有一个原型,Javascript的继承机制是通过模拟Java来实现的,并非真正严格意义上的继承,被继承的对象(Java中称为父类或超类)称为继承对象的原型,JavaScript中的所有的对象(包括自定义的对象)都有原型,没有指定原型的对象其原型默认为Object,Object是所有对象原型的根,Object中有prototype、constructor两个属性及hasOwnproperty(property)、isprototypeOf(Object)toString(),valueOf()等方法函数,这就意味着所有的对象(包括自定义的对象)都有这些属性及方法。
(以下为转)
首先说类,要声明的是,至少到目前为止Javascript中没有类,所谓的“类”其实不是真正的类,它只是表现的像其他面向对象的语言中的类而已,它的本质是函数+原型对象(prototype)。有人说javascript也是面向对象的,只是它是prototypebased,当然这只是概念上的区别,我不想讨论js是不是面向对象的,关键是想说明虽然javascript的类表现得很像其他语言中的类,但是内部的实现机理确不太一致,如果一味的把javascript中的类类比作其他语言中的类,有时候脑子会犯混。
先看一段简单的代码,一般教材上介绍如何新建一个类的时候都是这样的(当然还有更复杂的方法,不过本质上是一样的):
functionMyClass(x){ this.x=x; } varobj=newMyClass('Helloclass'); alert(obj.x);
毫无疑问,此时obj具有一个x属性,现在的值是Helloclass.但是,obj到底是什么?MyClass仅仅是一个函数而已,我们称之为构造函数。在其他OO的语言中,构造函数是要放在class关键字内部的,也就是先要声明一个类。另外,函数体内的this又是什么?其他OO语言中,this的概念是很明确的,就是当前对象,因为它在构造函数执行之前已经声明了类,类的内部的一些字段都是已经定义好的。
先解释下,在javascript的函数中,this关键字表示的是调用该函数的作用域(scope),作用域的概念也不是太好理解,下面再解释。不过可以简单的认为它是调用函数的对象。再看MyClass函数,它内部的this是什么呢?
如果我们把代码改成:
varobj=MyClass('Helloclass');
这是完全合乎语法的。如果这段代码是在浏览器中运行的,调试一下可以发现,this是window对象。而和obj没有任何关系,obj还是undefined,alert也不会有结果。原来的代码之所以可以工作,都是new关键字的功劳。new关键字把一个普通的函数变成了构造函数。也就是说,MyClass还是一个普通的函数,它之所以能构造出一个obj,基本上是new的功劳。当函数之前有new关键字的时候,javascript会创造一个匿名对象,并且把当前函数的作用域设置为这个匿名对象。然后在那个函数内部引用this的话就是引用的这个匿名对象,最后,即使这个函数没有return,它也会把这个匿名对象返回出去。那么obj自然就具有了x属性。
现在这个MyClass已经有点像一个类了。但是,这并不是new的工作的全部。Javascript同样可以方便的实现继承——依靠是prototype.prototype也是一个对象,毕竟除了原始类型,所有的东西都是对象,包括函数。更为重要的是,前面提到javascript是prototypebased,它的含义就是在javascript中没有类的概念,类是不存在的,一个函数,它之所以表现的像类,就是靠的prototype.prototype可以有各种属性,也包括函数。上一段说的new在构造对象的过程中,在最终返回那个匿名对象之前,还会把那个函数的prototype中的属性一一复制给这个对象。这里的复制是复制的引用,而不是新建的一个对象,把内容复制过来,在其内部,相当于保留了一个构造它的函数的prototype的引用。有些教材含糊的说所有的“所有对象都有一个prototype属性”,这种说法是不确切的,虽然它内部确实有一个prototype属性,但是对外是不可见的。只有函数对象是有prototype属性的,函数对象的prototype默认有一个constructor属性。
看如下的代码:
functionMyClass(x){ this.x=x; } varproObj=newMyClass('x'); InheritClass.prototype=proObj; MyClass.prototype.protox='xxx'; functionInheritClass(y){ this.y=y; } varobj=newInheritClass('Helloclass'); MyClass.prototype.protox='changed'; proObj.x='ChangedToo'; alert(obj.protox); alert(obj.x);
输出的结果是changed和ChangedToo。此代码说明了对象内部保留的是构造函数的prototype的引用,要注意的是,proObj中也是保留的它的构造函数的prototype的引用。如果把代码改成:
varobj=newInheritClass('Helloclass'); proObj.protox='Iamwinner'; MyClass.prototype.protox='changed'; proObj.x='ChangedToo'; alert(obj.protox); alert(obj.x);
输出的就是Iamwinner和ChangedToo了。事实上,这些prototype逐层引用,构成了一个prototype链。当读取一个对象的属性的时候,首先寻找自己定义的属性,如果没有,就逐层向内部隐含的prototype属性寻找。但是在写属性的时候,就会把它的引用覆盖掉,是不会影响prototype的值的。
再介绍闭包,首先说明下,这里的闭包(closure)和离散数学中关系的传递闭包中的不是一个概念,我曾以为他们之间有关联,后来仔细想想,似乎并无什么关联,恰好名字一样而已。先看定义:
Closure
A"closure"isanexpression(typicallyafunction)thatcanhavefreevariablestogetherwithanenvironmentthatbindsthosevariables(that"closes"theexpression).
要完全理解闭包需要对Javascript函数的机理有比较透彻的理解,而这个机理有点复杂,并不是三言两语能讲清的,即使是这篇文章,也只是大概讲了下原理。大意就是任何一个函数调用都在一个运行上下文(ExecutionContext)中执行的,这个上下文中有一个作用域对象,其中包括了这个函数的局部变量、参数等。另外,如果一个函数是一个内部函数,它的作用域中含有它外部函数的作用域。在内部函数遇到一个变量名的时候,它是从内部的作用域找起,不断往外层的作用域找。因此,如果内部函数作为一个对象返回出外部函数的时候,即使外部函数已经执行完毕,但是由于其内部函数仍有引用指向它,内部函数不会被释放,因为内部函数有外部函数的作用域,因此外部函数的局部变量也不会被释放。这就构成了闭包。
相关文章推荐
- AutoCAD .Net开发指南第4部分关于标注和公差的内容翻译完了!
- js中关于时间的一些函数
- 关于HTML5视频播放的一些内容(1)
- 关于ajax请求数据后,数据本身的js失效的一些想法
- oracle 11g GRID 中 关于 OLR 须要知道的一些内容
- 汉字的一些关注点,Microsoft Visual Studio International Feature Pack 2.0 数值到大写的转化,汉字翻译成日文韩文,文本框内容的对其,etc
- js-权威指南学习笔记19
- Js获取当前日期时间和我的JQ关于日期的一些例子
- 关于js页面时间判断,和一些杂项
- Concept内容的翻译_1025(英语水平差,发出来主要是想让大家帮我指正一下,谢谢!)
- 关于JS文件合并的一些衍生想法
- html,css jq,js关于多行,单行文字内容溢出用点点点(...)省略号表示
- js中关于可视区、实际区域一些知识的个人理解
- 关于原生js的一些研究
- Node.js权威指南 (5) - 使用Buffer类处理二进制数据
- js-权威指南学习笔记9
- JS权威指南学习笔记之脚本化文档
- 关于UIWebView的一些应用,包括与JS交互,前进,后退等
- 关于oracle rowid的一些内容
- js权威指南