今天再读了《JS高程》的第六章,有了些深入的感悟和理解,总结分享一下。

创建对象的方式有很多,有一种是动态原型模式,最实用的是构造函数与原型组合的模式,原型的动态性在这两个模式里都有所体现,我本人的理解是:前者的“动态”是通过一些判断,看方法是否存在来决定是否对原型进行初始化,同时,在构造函数内部对原型的修改会立即体现在所有的实例中,后者的“动态”是主要是说无论是先创建实例还是先修改原型,对原型对象所做的修改都会立即反应在实例中,针对后者来个栗子(栗子1):

function Person(){}
var p = new Person();
Person.prototype.sayHello = function(){
alert("Hello!");
}
p.sayHello(); //弹出:Hello

其实,实例与原型之间的关联纽带就是一个定向指针,因此,我感觉构造函数与实例某种程度上是平等关系,只不过构造函数拥有原型指过来的一个指针(constructor)。

到这里,一切都很好理解,偏偏文章接下来有扩展了一点儿内容把我搞迷糊了,直接上码(栗子2):

function Person(){}
Person.prototype = {
constructor : Person,
name : "Tom",
age : 29,
sayName : function(){
alert(this.name);
}
}
var p = new Person();
p.sayName(); //弹出:"Tom"

那好,既然上边说了,原型有动态性,那我这样写(栗子3):

function Person(){}
var p = new Person();
Person.prototype = {
constructor : Person,
name : "Tom",
age : 29,
sayName : function(){
alert(this.name);
}
}
p.sayName(); //error

按理说,我实例调用了原型上的方法,应该弹出“Tom”啊,事实上却报错:“undefined is not a function”。

其实,这已经不再是原型动态不动态的问题了,而是实例与新、旧原型对象之间的问题。另外原型与实例间关系,我们可以用isPrototypeOf或者instanceof等来判断。

我们都看到了,栗子1与栗子2、3对原型的修改方式是不一样的,栗子1相当于纯粹的给原型这个对象添加了一个方法,而栗子2、3用的是字面量法创建了一个新的原型(相当于新建一个对象),完完全全,彻彻底底地覆盖了原来的原型对象,只不过用一句“constructor:Person;”伪装了一下,仔细的读者或许会发现我在第二段的说明是给"修改"这个词加粗了,栗子1只是“修改”,栗子2、3是“新建覆盖”。

栗子2中创建实例对象时,原来的原型已经被新建的原型覆盖了,因此能够访问到这个方法。而栗子3中,当创建实例时,它的指针指向的还是之前的原型,即便后来又新建了一个原型对象,这个指针依然没变,一次在原来原型上是访问不到这个方法的,故报错。语言的描述显得很干巴巴,我们再来个栗子(栗子4):

function Person(){}
Person.prototype = {
name : "Tom",
age : 29,
sayHello : function(){
alert("Hello");
}
}
var proto = Person.prototype;
var p = new Person();
p.syaHello(); //Hello
alert(Person.prototype.isPrototypeOf(proto)); //false
alert(Person.prototype.isPrototypeOf(p)); //true
alert(proto.isPrototypeOf(p)); //true

上述代码非常清晰的告诉我们:proto里保存的始终是原来的原型对象,而alert里的Person.prototype是已经被覆盖了的新的原型对象,p此时访问的也是新的原型对象。

最后来个栗子(栗子5):

function Person(){}
Person.prototype = {
var proto = Person.prototype;
var p = new Person();
name : "Tom",
age : 29,
sayHello : function(){
alert("Hello");
}
}
p.syaHello(); //error
alert(Person.prototype.isPrototypeOf(proto)); //false
alert(Person.prototype.isPrototypeOf(p)); //false
alert(proto.isPrototypeOf(p)); //true

上述代码非常清晰的告诉我们:proto里保存的依然是原来的原型对象,p此时访问的还是原来的原型对象。

综上,个人感觉这两部分的内容不应该放在一块儿说,很容易让人迷糊,其次,看问题,一定能进得去、跳的出,遇到死角,站在更高的角度看一下,就会有新的发现,自己在看这块儿时一直拐不过来弯儿,分明前边说了有动态性,后边确没有体现,并且还相违背,这分明不合理,后来才发现,这其实是两码事儿,应该分开来理解。

(另:这是JS里比较重要的模块儿,本人才学疏浅、难免疏漏,欢迎指正,共同进步^_^)

【原】JS原型的动态性及实例与原型的关系的更多相关文章

  1. JavaScript中的 原型 property 构造函数 和实例对象之间的关系

    1 为什么要使用原型? /* * javascript当中 原型 prototype 对象 * * */ //首先引入 prototype的意义,为什么要使用这个对象 //先来写一个构造函数的面向对象 ...

  2. JS高级. 03 混入式继承/原型继承/经典继承、拓展内置对象、原型链、创建函数的方式、arguments、eval、静态成员、实例成员、instanceof/是否在同一个原型链

    继承:当前对象没有的属性和方法,别人有,拿来给自己用,就是继承 1 混入式继承 var I={ }; var obj = { name: 'jack', age:18, sayGoodbye : fu ...

  3. Js笔记(对象,构造函数,原型,原型链,继承)及一些不熟悉的语法

    对象的特性: 1.唯一标识性,即使完全不一样的对象,内存地址也不同,所以他们不相等 2.对象具有状态,同一个对象可能处在不同状态下 3.对象具有行为,即对象的状态可能因为他的行为产生变迁 Js直到es ...

  4. Js 面向对象之封装,继承,原型,原型链

    封装 ,继承 ,原型, 原型链 封装 ? 面向对象有三大特性,封装.继承和多态.对于ES5来说,没有class(类)的概念,并且由于JS的函数级作用域(函数内部的变量在函数外访问不到),所以我们就可以 ...

  5. js生成随机数的方法实例总结 [收藏]

    js生成随机数的方法实例总结 js生成随机数主要用到了内置的Math对象的random()方法.用法如:Math.random().它返回的是一个 0 ~ 1 之间的随机数.有了这么一个方法,那生成任 ...

  6. 《JS权威指南学习总结--6.1原型》

    内容要点: 一.每一个JS对象(null除外)都和另一个对象相关联."另一个"对象就是我们熟知的原型,每一个对象都从原型继承属性. 二.所有通过对象直接量创建的对象都具有同一个原型 ...

  7. JS 原型链 prototypt 和隐式原型 _proto_

    prototype(原型) :  对象的一个属性,此属性使您有能力向对象添加属性和方法,当访问对象不存在属性是会自动到 prototype 中找 _proto_(隐式原型): 此对象构造函数(类)的原 ...

  8. JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)

    什么是面向对象?面向对象是一种思想. 面向对象可以把程序中的关键模块都视为对象, 而模块拥有属性及方法. 这样如果我们把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.   工厂 ...

  9. 构造函数、原型对象prototype、实例、隐式原型__proto__的理解

    (欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指出来~) PS: 内容中的__proto__可能会被markdown语法导致显示为proto. 建议将构造函数中的方法都定义到构造函数的原 ...

随机推荐

  1. PAT (Basic Level) Practise:1019. 数字黑洞

    [题目链接] 给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有“数字黑洞” ...

  2. c语言二叉树基本操作

    编译器为vs2013 #include "stdafx.h" #include<malloc.h> #include<stdlib.h> #define O ...

  3. 加载json文件没显示图片

    IOS 9新特性要求App内访问的网络必须使用HTTPS协议. 但是现在公司的项目使用的是HTTP协议,使用私有加密方式保证数据安全.现在也不能马上改成HTTPS协议传输. 以下解决办法: 在info ...

  4. yii使用MongoDB作为数据库服务软件[win7环境下](1)

    1.进入http://php.net,在站内搜索栏搜索mongodb,查看相关的安装步骤信息. 2.找到相应的php.ini配置文件,使用wampserver等服务器软件时,千万不要找错了php.in ...

  5. iOS红马甲项目Bug总结(3)

    这里是一些小总结 1.使用图片缓存之后,新添加的图像一直不能显示 2.项目打包通过appliction loader上传成功了,可是itunes 上面的构建版本项,一直没显示出来 3.界面加载之后,t ...

  6. POI给Excel添加数字筛选

    HSSFSheet sheet = workbook.createSheet("list"); CellRangeAddress ce = CellRangeAddress.val ...

  7. django1.9.6 使用 DjangoUeditor (python3.5)

    DjangoUeditor https://github.com/zhangfisher/DjangoUeditor 1 DjangoUeditor 安装 pip install DjangoUedi ...

  8. CentOS中Device eth0 does not seem to be present错误解决办法

    今天克隆的虚拟机,当需要多台虚拟机的时候,试用克隆真是方便,不过遇到了 Device eth0 does not seem to be present 的问题,在网上找到遇到同样问题的解决方法, 很顺 ...

  9. Android Studio IDE 简单学习和介绍

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  10. MapReduce 2简介

    在Hadoop 1.0版本中,mapred.job.tracker决定了执行MapReduce程序的方式,若设置为local,则使用本地的作业运行器,若设置为主机:端口(eb179:9001),则该配 ...