JavaScript 原型对象和原型链

开篇

之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你没有真正的理解。最近正在读《Javascript高级程序设计》,书中对原型对象和原型链的描述让我受益匪浅,下面仅用一个对比性的例子来说明。

我们经常会这么写

1     function Person () {
2         this.name = ‘John‘;
3     }
4     var person = new Person();
5     Person.prototype.say = function() {
6         console.log(‘Hello,‘ + this.name);
7     };
8     person.say();//Hello,John

上述代码非常简单,Person原型对象定义了公共的say方法,虽然此举在构造实例之后出现,但因为原型方法在调用之前已经声明,因此之后的每个实例将都拥有该方法。从这个简单的例子里,我们可以得出:

原型对象的用途是为每个实例对象存储共享的方法和属性,它仅仅是一个普通对象而已。并且所有的实例是共享同一个原型对象,因此有别于实例方法或属性,原型对象仅有一份。

所有就会有如下等式成立:

  person.say == new Person().say

可能我们也会这么写

 1     function Person () {
 2         this.name = ‘John‘;
 3     }
 4     var person = new Person();
 5     Person.prototype = {
 6         say: function() {
 7             console.log(‘Hello,‘ + this.name);
 8         }
 9     };
10     person.say();//person.say is not a function

很不幸,person.say方法没有找到,所以报错了。其实这样写的初衷是好的:因为如果想在原型对象上添加更多的属性和方法,我们不得不每次都要写一行Person.prototype,还不如提炼成一个Object来的直接。但是此例子巧就巧在构造实例对象操作是在添加原型方法之前,这样就会造成一个问题: 当var person = new Person()时,Person.prototype为:Person {}(当然了,内部还有constructor属性),即Person.prototype指向一个空的对象{}。而对于实例person而言,其内部有一个原型链指针__proto__,该指针指向了Person.prototype指向的对象,即{}。接下来重置了Person的原型对象,使其指向了另外一个对象,即 Object {say: function}, 这时person.__proto__的指向还是没有变,它指向的{}对象里面是没有say方法的,因为报错。 从这个现象我们可以得出:

在js中,对象在调用一个方法时会首先在自身里寻找是否有该方法,若没有,则去原型链上去寻找,依次层层递进,这里的原型链就是实例对象的__proto__属性。

若想让上述例子成功运行,最简单有效的方法就是交换构造对象和重置原型对象的顺序,即:

 1     function Person () {
 2         this.name = ‘John‘;
 3     }
 4     Person.prototype = {
 5         say: function() {
 6             console.log(‘Hello,‘ + this.name);
 7         }
 8     };
 9     var person = new Person();
10     person.say();//person.say is not a function

一张图让你秒懂原型链

其实,只需要明白原型对象的结构即可:

1     Function.prototype = {
2         constructor : Function,
3         __proto__ : parent prototype,
4         some prototype properties: ...
5     };

总结:

函数的原型对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针__proto__,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用__proto__一直指向Object的原型对象上,而Object的原型对象用Object.proto = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。

文章学习自https://kkkkkxiaofei.github.io/jekyll/update/2015/06/03/proto.html

时间: 2024-10-08 10:09:26

JavaScript 原型对象和原型链的相关文章

javascript之对象,原型链

对象 ECMAScript是高度抽象的面向对象语言,处理对象的.同样也有基本类型,但是他们在需要的情况下,也可以转型成对象. 定义: 对象是拥有一系列属性以及唯一的原型对象.那原型对象可能是对象,也可能为空. 让我们看一个基本对象的例子.对象的原型是通过内部的[[Prototype]]来引用的.然而,我们将会用 __<internal_property>__ 下化线符号替代双中括号,那么对于原型对象: __proto__. 对于下面代码: var foo = { x: 10, y:20 };

Js 原型对象与原型链

原型对象 每个javascript对象都有一个原型对象,这个对象在不同的解释器下的实现不同.比如在firefox下, 每个对象都有一个隐藏的__proto__属性,这个属性就是"原型对象"的引用. 原型链 由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自 己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本 身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则

一个例子让你明白原型对象和原型链

开篇 之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述.有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你没有真正的理解.最近正在读<Javascript高级程序设计>,书中对原型对象和原型链的描述让我受益匪浅,下面仅用一个对比性的例子来说明. 我们经常会这么写 function Person () { this.name = 'John'; } var person = new Person(

JavaScirpt中的原型,原型对象和原型链

一.什么是原型呢? 我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象.(即prototype即为函数的原型该原型指向的是一个原型对象) 二.什么是原型对象呢? 我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象(即原型对象).而这个对象的用途是包含 可以由特定类型的所有 实例 共享的属性和方法.(字面意思prototype就是通过调用构造函数而创建的实例对象的原型对象) 使用原型对象的好处是可以让所有的对象实例(实

js(三) 原型对象与原型链

原型对象 每个javascript对象都有一个原型对象 原型链 由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefined.原型链一般实现为一个链表,这样就可以按照一定的顺序来查找. 一.指定对象字面量的原型 示例1 思想方法:把一些对象共享的方法.属性,

(转)认识原型对象和原型链

在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象 Object 和 函数对象 Function. 一般而言,通过 new Function 产生的对象是函数对象,其他对象都是普通对象. 举例说明: function f1() { // todo } var f2 = function () { // todo }; var f3 = new Function('x', 'console.log(x)'); var o1 = {}; var o2 = new O

函数的原型对象和原型链?

函数的原型对象: 我们创建的每一个函数都有一个prototype(原型)属性,该属性是一个指针,该指针指向了一个对象(原型对象).对于我们创建的构造函数,该对象中包含可以由所有实例共享的属性和方法. 函数的原型属性prototype指向一个原型对象,这对象中都会自动包含一个constructor(构造函数)属性. 构造函数的原型属性为prototype;而实例化的函数对象的属性为 _proto_, _proto_继承于构造函数的原型属性. __proto__是每个对象都有的一个属性,而proto

浅谈JS中的原型对象和原型链

我们知道原型是一个对象,其他对象可以用它实现属性继承,除了prototype,又有__proto__ 1. prototype和__proto__的区别 prototype是函数才有的属性                                     __proto__是每个对象都有的属性 但是__proto__不是一个规范的属性,只是部分浏览器 实现了此属性,对应标准的属性是[[Prototype]] 2. __proto__属性指向谁? __proto__的指向取决于对象创建时的实

原型,原型对象,原型链,构造函数,继承(一)

前言:javascript中 万物皆对象 , 但是对象是有区别的 分为普通对象(object)和函数对象(function): ①由以下三种形式创建的对象为函数对象: function fun1(){} var fun2 = function(){} var fun3 = new Function(); console.log(typeof fun1);//function console.log(typeof fun2);//function console.log(typeof fun3);