这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
我们先看一段传统的继承代码:
JS 中原型的概念不想多说,这里只是探讨一下修改父类原型属性与覆盖父类原型中属性的区别,防止以后出问题
- //定义超类
- function Father(){
- this.name = "父亲";
- }
- Father.prototype.theSuperValue = ["NO1","NO2"];
- //定义子类
- function Child(){
- }
- //实现继承
- Child.prototype = new Father();
- //修改共享数组
- Child.prototype.theSuperValue.push("修改");
- //创建子类实例
- var theChild = new Child();
- console.log(theChild.theSuperValue); //["NO1","NO2","修改"]
- //创建父类实例
- var theFather = new Father();
- console.log(theFather.theSuperValue); //["NO1","NO2","修改"]
通过上面的代码,我们注意 "加红" 的代码,子类 Child 的原型对象是父类 Father 的一个实例(new Father()),我们在这里是调用 new Father()对象中的 theSuperValue 属性,因为 new Father()对象中没有此属性(只有 name 属性),因此会沿着原型链向它的原型对象(Father.prototype)中去找,找到后发现是一个数组,而且是引用类型,此时我们往此数组中添加一个字符串" 修改 "。 之后,我们新建了 Child 的实例对象 theChild,当 theChild 调用 theSuperValue 属性时,首先它自己里面没有此属性,就会去它的原型对象 (new Father) 中去找,可惜这里也没有,接着会到 new Father()的原型中去找,OK,在 Father.prototype 中找到了这个数组,发现是["NO1","NO2"," 修改 "]。 再接着,我们创建了 Father 的实例对象 theFather,同上,我们在 Father.prototype 中找到了这个引用类型的数组["NO1","NO2"," 修改 "]。(当然,数组都是引用类型的!) 通过上面的赘述,本来已经理解原型链概念的朋友觉得是废话连篇,其实我也是呵呵,接下来我们再看一个相似的例子:
- //定义超类
- function Father() {
- this.name = "父亲";
- }
- Father.prototype.theSuperValue = ["NO1", "NO2"];
- //定义子类
- function Child() {
- }
- //实现继承
- Child.prototype = new Father();
- //修改共享数组
- Child.prototype.theSuperValue = ["我是覆盖代码"]
- //创建子类实例
- var theChild = new Child();
- console.log(theChild.theSuperValue);
- //创建父类实例
- var theFather = new Father();
- console.log(theFather.theSuperValue);
我们看一下上面的代码,我用一种比较特别的紫色标注了此段代码与上段代码的小小区别,但结果却发生了 "巨大" 变化,见下面的截图:
为什么我说是巨大变化,是因为我们从 "重用公共属性" 过渡到 "覆盖公共属性,建立自己特色属性" 上来!我这里是用数组演示的,其实第二种情况常常用在 Function 中,用子类的方法来覆盖父类的方法。在第二段代码中,我们需要关注的是紫色代码前的 "=" 号,它是赋值操作符。如果我们对 Child.prototype 及 new Father() 对象调用这个赋值操作符时,我们就在这个对象上" 新建 "了一个属性,当在下面的 theChild 实例上调用 theSuperValue 时,返回的当然是新属性值 [" 我是覆盖代码 "]。 但当我们新创建一个父类实例 theFather 对象时,调用该对象上的 theSuperValue 属性,我们就会发现对象上并没有啊,这是为什么呢?因为我们刚才覆盖的是 Father 对象 new Father(); 而不是 Father 类,所以,通过 Fater()构造函数创建的新对象 theFather 并不包含新建的属性,当然,接下来的事情大家都明白,就是沿着原型链向上找,OK,在 Father.prototype 中找到了,就是我们一开始定义的那个数组。 通过上面两个例子,我们在 JS 中使用原型提供的继承功能时,尤其是利用子对象操作原型方法、对象时,切记 "=" 号赋值与引用调用这两种不同的操作,因为他们会带来完全不同的结果。
来源: http://www.phperz.com/article/17/0427/281751.html