【原】JS原型的动态性及实例与原型的关系
今天再读了《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原型的动态性及实例与原型的关系的更多相关文章
- JavaScript中的 原型 property 构造函数 和实例对象之间的关系
1 为什么要使用原型? /* * javascript当中 原型 prototype 对象 * * */ //首先引入 prototype的意义,为什么要使用这个对象 //先来写一个构造函数的面向对象 ...
- JS高级. 03 混入式继承/原型继承/经典继承、拓展内置对象、原型链、创建函数的方式、arguments、eval、静态成员、实例成员、instanceof/是否在同一个原型链
继承:当前对象没有的属性和方法,别人有,拿来给自己用,就是继承 1 混入式继承 var I={ }; var obj = { name: 'jack', age:18, sayGoodbye : fu ...
- Js笔记(对象,构造函数,原型,原型链,继承)及一些不熟悉的语法
对象的特性: 1.唯一标识性,即使完全不一样的对象,内存地址也不同,所以他们不相等 2.对象具有状态,同一个对象可能处在不同状态下 3.对象具有行为,即对象的状态可能因为他的行为产生变迁 Js直到es ...
- Js 面向对象之封装,继承,原型,原型链
封装 ,继承 ,原型, 原型链 封装 ? 面向对象有三大特性,封装.继承和多态.对于ES5来说,没有class(类)的概念,并且由于JS的函数级作用域(函数内部的变量在函数外访问不到),所以我们就可以 ...
- js生成随机数的方法实例总结 [收藏]
js生成随机数的方法实例总结 js生成随机数主要用到了内置的Math对象的random()方法.用法如:Math.random().它返回的是一个 0 ~ 1 之间的随机数.有了这么一个方法,那生成任 ...
- 《JS权威指南学习总结--6.1原型》
内容要点: 一.每一个JS对象(null除外)都和另一个对象相关联."另一个"对象就是我们熟知的原型,每一个对象都从原型继承属性. 二.所有通过对象直接量创建的对象都具有同一个原型 ...
- JS 原型链 prototypt 和隐式原型 _proto_
prototype(原型) : 对象的一个属性,此属性使您有能力向对象添加属性和方法,当访问对象不存在属性是会自动到 prototype 中找 _proto_(隐式原型): 此对象构造函数(类)的原 ...
- JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
什么是面向对象?面向对象是一种思想. 面向对象可以把程序中的关键模块都视为对象, 而模块拥有属性及方法. 这样如果我们把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作. 工厂 ...
- 构造函数、原型对象prototype、实例、隐式原型__proto__的理解
(欢迎一起探讨,如果有什么地方写的不准确或是不正确也欢迎大家指出来~) PS: 内容中的__proto__可能会被markdown语法导致显示为proto. 建议将构造函数中的方法都定义到构造函数的原 ...
随机推荐
- SVD
SVD分解(奇异值分解),本应是本科生就掌握的方法,然而却经常被忽视.实际上,SVD分解不但很直观,而且极其有用.SVD分解提供了一种方法将一个矩阵拆分成简单的,并且有意义的几块.它的几何解释可以看做 ...
- codeforces298c
link:http://codeforces.com/problemset/problem/298/C 这道题目可以看出来我智商确实拙计 #include <iostream> #incl ...
- appserv升级php
安装thinkphp的时候提示必须要php5.3及以上 本地测试服务器使用的是appserv集成环境 所以要单独升级php 首先到官网下载http://php.net/downloads.php wi ...
- pt-ioprofile分析查看mysql的真实IO情况
针对IO密集型应用做系统调优的时候,我们通常都需要知道系统cpu 内存 io 网络等系统性能 和 使用率,结合应用本身的访问量,以及 mysql的性能指标来综合分析.比如说:我们将系统压力情况分为 ...
- Android学习一:文件操作
最近在学习安卓相关的编程,对于一门新技术的学习,我想应该跟其他语言一样吧,如C++和C#,也是文件,网络,多线程以及数据库之类的学习了.所以决定先从文件下手,现在将文件的一点学习列在下面: 1.Jav ...
- linux服务之maven
curl -O http://mirrors.noc.im/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.zip [root@d ...
- javascript中的对象之间继承关系
相信每个学习过其他语言的同学再去学习JavaScript时就会感觉到诸多的不适应,这真是一个颠覆我们以前的编程思想的一门语言,先不要说它的各种数据类型以及表达式的不同了,最让我们头疼,恐怕就是面向对象 ...
- AHS日志收集的三种方法
硬件环境:(描述实验机器初始环境) 型号 DL380 G8 序列号 配置扩展 备注 软件环境: □ 操作系统:无 连接方式: □ 无 实验步骤: 1在ILO里点information点 ...
- Navicat(连接) -1之HTTP 设置
HTTP 设置 HTTP 通道是一种连接到服务器的方法,使用与网络服务器相同的通讯协定(http://)和相同的端口(端口 80).这是当你的互联网服务供应商不允许直接连接,但允许创建 HTTP 连接 ...
- AngularJS 中利用 Interceptors 来统一处理 HTTP 的错误(reproduce)
原文:http://chensd.com/2016-03/Angular-Handle-Global-Http-Error-with-Interceptors.html?utm_source=tuic ...