关于JavaScript中原型继承中的一点思考

 更新时间:2012年07月25日 11:48:59   作者:  
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中使用原型提供的继承功能时,尤其是利用子对象操作原型方法、对象时,切记“=”号赋值与引用调用这两种不同的操作,因为他们会带来完全不同的结果。

相关文章

  • JS显示日历和天气的方法

    JS显示日历和天气的方法

    这篇文章主要介绍了JS显示日历和天气的方法,涉及JavaScript日期与时间的操作技巧,非常简单实用,需要的朋友可以参考下
    2016-03-03
  • JS小知识之如何将CSV转换为JSON字符串

    JS小知识之如何将CSV转换为JSON字符串

    CSV文件一般是以逗号为分隔值的文件(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本),下面这篇文章主要给大家介绍了JS小知识之如何将CSV转换为JSON字符串的相关资料,需要的朋友可以参考下
    2023-06-06
  • JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)

    JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)

    最近做项目遇到表单在输入后立即验证,而不是提交后再验证,在网上找了下资料,没有合适的,于是我自己动手写了一个,分享到脚本之家平台,供大家参考
    2017-06-06
  • 详谈js对url进行编码和解码(三种方式的区别)

    详谈js对url进行编码和解码(三种方式的区别)

    下面小编就为大家带来一篇详谈js对url进行编码和解码(三种方式的区别)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • JS 控制小数位数的实现代码

    JS 控制小数位数的实现代码

    上网查一查的确存在这种Bug,除了位数上控制之外也没什么也好的方法(希望高手能提出其它思路)。
    2011-08-08
  • 详解用webpack把我们的业务模块分开打包的方法

    详解用webpack把我们的业务模块分开打包的方法

    本篇文章主要介绍了用webpack把我们的业务模块分开打包的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • js核心基础之构造函数constructor用法实例分析

    js核心基础之构造函数constructor用法实例分析

    这篇文章主要介绍了js核心基础之构造函数constructor用法,结合具体实例形式分析了javascript构造函数constructor概念、原理、使用方法及相关操作注意事项,需要的朋友可以参考下
    2019-05-05
  • JS短路原理的应用示例 精简代码的途径

    JS短路原理的应用示例 精简代码的途径

    正如标题所言,js中||和&&的特性帮我们精简了代码的同时,也带来了代码可读性的降低。这就需要我们自己来权衡了,下面有个不错的示例
    2013-12-12
  • Boostrap中栅格布局的实现

    Boostrap中栅格布局的实现

    这篇文章主要为大家详细解析了Boostrap 栅格布局,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2017-01-01
  • echarts柱状图坐标轴内容显示不全的两种解决办法

    echarts柱状图坐标轴内容显示不全的两种解决办法

    本文主要介绍了echarts柱状图坐标轴内容显示不全的两种解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05

最新评论