JavaScript 原型链学习(一)原型对象

在JavaScript中创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有的实例共享的属性和方法。如果按照字面意思来理解,那么prototype就是通过调用构造函数而创建那个实例的原型对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。换句话说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中,如下例所示:

function Person(){}

Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
  alert(this,name);
};

var person1 = new Person();
person1.sayName();     // "Nicholas"

var person2 = new Person();
person2.sayName();     // "Nicholas"

alert(person1.sayName == person2.sayName);    //true

本例中将sayName()方法和所有属性直接添加到了Person的prototype属性中,构造函数变成了空函数。即使如此,也仍然可以通过调用构造函数来创建新对象,而且新对象还会具有相同的属性和方法,同时这些属性和方法是由所有实例共享的。换句话说,person1和person2访问的都是同一组属性和同一个sayName()函数。

原型对象的性质

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象。在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性是一个指向prototype 属性所在函数的指针。就拿前面的例子来说,Person.prototype.constructor指向Person。而通过这个构造函数,我们还可继续为原型对象添加其他属性和方法。

创建了自定义的构造函数之后,其原型对象默认只会取得constructor属性;至于其他方法,则都是从Object继承而来的。当调用构造函数创建一个新实例后, 该实例的内部将包含一个指针 (内部属性)指向构造函数的原型对象。ECMA-262第5版中管这个指针叫[[Prototype]]。虽然在脚本中没有标准的方式访问 [[Prototype]] 但Firefox、Safari 和Chome在每个对象上都支持一个属性 __proto__ ;而在其他实现中,这个属性对脚本则是完全不可见的。不过,要明确的真正重要的一点就是,这个连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。

用上例中使用的 Person 构造函数和 Person.prototype 创建实例的代码为例,下图展示了各个对象之间的关系。

上图展示了Person构造函数Person 的原型属性以及Person现有的两个实例之间的关系。在此,Person.prototype指向了原型对象,而Person.prototype.constructor又指回了Person。原型对象中除了包含constructor属性之外,还包括后来添加的其他属性。 Person的每个实例——person1和person2都包含一个内部属性,该属性仅仅指向了Person.prototype;换句话说,它们与构造函数没有直接的关系。此外,要格外注意的是,虽然这两个实例都不包含属性和方法,但我们却可以调用person1.sayName()。这是通过查找对象属性的过程来实现的。

虽然在所有实现中都无法访问到[[Prototype]],但可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。从本质上讲,如果[[Prototype]]指向调用isPrototypeOf()方法的对象(Person.prototype),那么这个方法就返回true,如下所示:

alert(Person.prototype.isPrototypeOf(person1));  / /true
alert(Person.prototype.isPrototypeOf(person2));  / /true

这里,用原型对象的isPrototypeOf()方法测试了person1  和person2。 因为它们内部都有一个指向Person.prototype的指针,因此都返回了true。

每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到了这个属性,则返回该属性的值。也就是说,在我们调用person1.sayName()的时候,会先后执行两次搜索。首先,解析器会问:“实例person1有sayName属性吗?” 答:“没有。” 然后,它继续搜索,再问:“person1 的原型有sayName属性吗?” 答:“有。” 于是,它就读取那个保存在原型对象中的函数。当我们调用person2.sayName()时,将会重现相同的搜索过程,得到相同的结果。而这正是多个对象实例共享原型所保存的属性和方法的基本原理。

虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,那我们就在实例中创建该属性,该属性将会屏蔽原型中的那个属性。

原文地址:https://www.cnblogs.com/weiyalin/p/9402319.html

时间: 2024-11-05 22:21:32

JavaScript 原型链学习(一)原型对象的相关文章

JavaScript ES5类 原型 原型链 组合、原型、寄生式继承

ES5类 原型  原型链 继承 JavaScript中,原型是相对于构造函数(类)的叫法(或者说概念),原型链是相对于构造函数(类)的实例对象的叫法. 对于JavaScript对象,如果在对象自身上找不到该属性,那么就会向上沿着原型链继续查找该属性 创建一个ES5类 在ES5中,类是由函数名首字母大写的函数,通过关键字new创建的. 类的构造函数就是函数自身 一般情况下,ES5类的原型对象prototype是自身构造函数,该类的实例化对象的原型链对象__proto__也是该构造函数,这二者指向同

javascript原型原型链 学习随笔

理解原型和原型链.需从构造函数.__proto__属性(IE11以下这个属性是undefined,请使用chrome调试).prototype属性入手. JS内置的好多函数,这些函数又被叫做构造函数.如:Object---Array---Function---Math---Date---String---Number---Boolean---Symbol---RegExp. JS里,所有的对象,都是其构造函数的实例.如{}是Object的一个实例,[]是Array的一个实例.fn() {}是Fu

JavaScript原型链学习

function foo(){} foo.prototype.z = 3; var obj = new foo(); obj.y = 2; obj.x = 1; obj.x; //1 obj.y; //2 obj.z; //3 typeof obj.toString; //'function' 'z' in obj; //true obj.hasOwnProperty('z'); //false 首先,我们通过function foo()去定义一个函数对象..那么,foo()对象自动带有prot

JavaScript原型与原型链学习笔记

一.什么是原型?原型是一个对象,其他对象可以通过它实现属性继承.简单的说就是任何一个对象都可以成为原型 prototype属性: 我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象包含可以有特定类型的所有实例共享的属性和方法.这个对象就是原型对象(也就是某个对象的原型所引用的对象).1.总之只要创建了函数,该函数都有一个prototype属性,指向函数的原型对象. 如上图,Person是一个函数,右侧的方框就是它的原型. 2.默认情况下所有原型对象都会

原型原型链学习记录

这是一篇学习笔记. 个人心得: 关于原型和原型链这一块,很难,但是,一旦理解,就通了. 对于这一块,我之前不懂的时候,非要去弄明白,特别痛苦,之后,看到了王福朋老师的闭包原型系列,真的是茅塞顿开!看完之后,我就拿起JavaScript高程3,高程3第6章节,耐心跟着看也就明白了.之后,再去做一些图解,如果能够根据继承画出所有的关系,没有矛盾的点,那就基本没问题了.再到网上找差不多的文章看,如果没有冲突点,那这一块就没问题了. 参考的内容: http://www.cnblogs.com/wangf

JS 原型链学习总结

废话篇: 在js的学习过程中有一大难点就是原型链.学习的时候一直对这一内容不是十分的明白.纠结的我简直难受.,型号总算给他弄通了,哇咔咔,总算可以不用在睡梦中还想着他了. 正文篇: 要了解原型链我们首先要记住的一点是JS中所有的东西都可以用对象来理解.函数在JS中实际上也是一个对象.然后再去看原型链的东西. 上图是首要的: 实际上我们可以吧JS中的对象看成两种,一种是我们所熟知的一般的对象,还有一种就是JS中所有的方法对象. 一般对象: 对于一般的对象而言,其实际上就是一个方法与属性的集合,而在

原型链学习总结

原型链 概念 原型链是一种机制,指的是JavaScript每个对象包括原型对象都有一个内置的[[proto]]属性指向创建它的函数对象的原型对象,即prototype属性. 作用 原型链的存在,主要是为了实现对象的继承. 理解 要理解原型链,需要从几个概念入手. 1.函数对象 在JavaScript中,函数即对象. 2.原型对象 当定义一个函数对象的时候,会包含一个预定义的属性,叫prototype,这就属性称之为原型对象. //函数对象 function F(){}; console.log(

JavaScript 原型链学习(三)原型对象存在的问题 与 组合使用构造函数和原型

原型对象也不是没有缺点.首先,它省略了为构造函数传递初始化参数这一环节, 结果所有实例在默认情况下都将取得相同的属性值.虽然这会在某种程度上带来一些不方便, 但还不是原型对象的最大问题.原型对象的最大问题是由其共享的本性所导致的.原型中所有属性是被很多实例共享的,这种共享对于函数非常合适.对于那些包含基本值的属性倒也说得过去,毕竟(如前面的例子所示),通过在实例上添加个同名属性, 可以隐藏原型中的对应属性.然而,对于包含引用类型值的属性来说,问题就比较突出了.来看下面的例子. function

通过JavaScript原型链理解基于原型的编程

零.此文动机 用了一段时间的Lua,用惯了Java C++等有Class关键字的语言,一直对Lua的中的面向对象技术感到费解,一个开源的objectlua更是看了n遍也没理解其中的原理,直到看到了Prototype-based programming 一.什么是基于原型的编程 基于原型的编程是面向对象编程的一种形式,通过复制已经存在的原型对象来实现面向对象,无与基于类的编程较大的区别是没有Class关键字,但是有类的概念.基于原型的编程也可以理解成基于实例的编程. 基于原型的系统可以在程序运行时