js原型理解
在学习之前,我们先对原型有一个大概的了解:
js中原型(prototype)就是一个指针,这个指针存在于每个函数对象中,它指向一个对象,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
先举个例子:
function Person(){ }
console.log(Person.prototype);
//"Object {constructor:function Person(),__proto__:Object} 见下文"
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
console.log(person1.__proto__); //{name,age,job,sayname}
在这个例子中我们在构造函数Person的原型对象prototype中申明了多个属性和方法,然后创建了他的实例person1,person2。可以看到person1和person2中都可以访问到同一个sayName函数。
1. 理解原型对象
无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype
属性,这个属性指向函数的原型对象。
constructor:
在默认情况下,所有原型对象都会自动获得一个 constructor
(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。就拿前面的例子来说,
Person.prototype.constructor 指向 Person 。
__proto__:
js中所有对象都默认包含一个指针[[Prototype]] (内部属性) ,指向构造函数的原型对象。虽然在js中没有标准的方式访问 [[Prototype]] ,但 Firefox、Safari 和 Chrome 在每个对象上都支持一个属性__proto__。在上例中person1.__proto__指向了构造函数的原型即Person.prototype,而Person.prototype.__proto__又指向了Object(原型对象是通过new Object创建的),这样的链式结构称之为原型链。

上图 展示了 Person 构造函数、 Person 的原型属性以及 Person 现有的两个实例之间的关系。在此, Person.prototype 指向了原型对象, 而 Person.prototype.constructor 又指回了 Person 。原型对象中除了包含 constructor 属性之外,还包括后来添加的其他属性。 Person 的每个实例——person1 和 person2 都包含一个内部属性,该属性仅仅指向了 Person.prototype ;换句话说,它们与构造函数没有直接的关系。此外,要格外注意的是,虽然这两个实例都不包含属性和方法,但我们却可以调用 person1.sayName()。这是通过查找对象属性的过程来实现的。
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(); var person2 = new Person(); person1.name = "Greg"; alert(person1.name); //"Greg" —— 来自实例 alert(person2.name); //"Nicholas" —— 来自原型
每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,则继续顺着原型链往上找。如果在原型对象中找到了这个属性,则返回该属性的值。也就是说,在我们调用 person1.sayName() 的时候,会先后执行两次搜索。首先,解析器会问: “实例 person1 有 sayName 属性吗?”答: “没有。 ”然后,它继续搜索,再问: “ person1 的原型有 sayName 属性吗?”答: “有。 ”于是,它就读取那个保存在原型对象中的函数。当我们调用 person2.sayName() 时,将会重现相同的搜索过程,得到相同的结果。而这正是多个对象实例共享原型所保存的属性和方法的基本原理。

浙公网安备 33010602011771号