今天再读了《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. python数据结构与算法——冒泡排序

    用两种方式实现,非递归和递归 直接上代码: 先是失败的递归方式,涉及到对象引用的问题: # Bad 想一想为啥不行? def bubblesort_rec_bad(A): if len(A)==1: ...

  2. windows 下的定时任务

    linux 下的定时任务是crontab 以前都是linux的定时任务,这次在windows做了定时任务,简单记录一下 windows 2008下的定时任务配置: 控制面板->管理工具-> ...

  3. Sprint第二个冲刺(第十三天)

    一.Sprint 计划会议: sprint2计划的功能还没有全部完成,还在实现剩余的两个功能模块,目前工作进展还比较顺利,争取下一个sprint完成剩余的所有目标. 以下是真机测试下的拍照和系统相册取 ...

  4. LintCode Reverse LinkedList (ArrayList 和 LinkedList 的区别)

    1. ArrayList 和 LinkedList 的区别 http://pengcqu.iteye.com/blog/502676 2. How to reverse LinkedList http ...

  5. Flex Builder读书笔记(二)——MXML

    MXML类似于HTML,它提供各种标签来定义用户界面,但是它比HTML的结构更为严格,并拥有跟多的应用标签.MXML不仅包括可视标签,还包括不可视标签,如web service连接.数据绑定和动画效果 ...

  6. Android 开发错误信息001

    Error:Execution failed for task ':app:dexDebug'. > com.android.ide.common.process.ProcessExceptio ...

  7. 基于KO+bootstrap+MVC的分页控件

    JS: /// <reference path="../knockout-3.2.0.js" /> var ViewModel = function (data) { ...

  8. HackerRank "Kruskal (MST): Really Special Subtree"

    Kruskal Algorithm is based on Union-Find - quite intuitive. #include <vector> #include <ios ...

  9. 四、Spring——Spring MVC

    Spring MVC 1.Spring MVC概述 Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet负责截获请求并将其分配给响应的处理器处 ...

  10. struts1 Demo

    每次都会忘记一些东西,反复查找原因,其实struts1很简单,可是不去巩固也很容易忘记并且犯错误.这是一个最简单的登录Demo. 1.建立web工程,引入struts1.2包 2.建package:a ...