一、对象中的原型_proto_
JavaScript中的对象是基于原型的。原型是其他对象的基础,它定义并实现了一个新创建的对象必须包含的成员列表。原型对象为所有对象实例所共享。
对象通过一个内部属性绑定到它的原型。在FireFox、Safari、和Chrome浏览器中,这个属性_proto_对开发者可见。一旦你创建一个内置对象(比如Object和Array)的实例,它们就会自动拥有一个Object实例作为原型。
因此,对象可以拥有两种成员类型:实例成员和原型成员。实例成员直接存于对象实例中,原型对象则从对象原型继承而来。
这就是为什么明明没有为对象定义 toString 方法,但是却可以在对象上调用此方法的原由。因为toString()是由对象person继承来的原型成员。
同样可以用 hasOwnProperty() 方法来判断对象是否包含特定的实例成员。要确定对象是否包含特定属性,可以用 in 操作符。
var book = { title: "High Performance JavaScript", author: "Nicholas C.Zakas" } console.log(book.hasOwnProperty(‘title‘)); //true console.log(book.hasOwnProperty(‘toString‘)); //false console.log("title" in book); //true console.log("toString" in book); //true
使用 in 操作符时,两种情况都会返回true,因为它既会搜索实例也会搜索原型。
二、函数中的原型prototype
每个函数创建后都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象包含了基于此函数创建的所有实例共享的属性和方法。换句话说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。(若原型对象中的值发生变化,继承了此原型对象的实例的对应值也会发生变化。不过如果该实例的某个继承来的属性被已经被重新赋值的话,便不会变化)。
//构造函数的两种写法 //1. 构造函数中的 this 绑定的是实例化后的对象,否则指向的是全局变量window var Person = function(){ this.name = ‘Kuro-P‘; this.age = 22; this.say = function(){ console.log(‘Hello‘); } } var p1 = new Person(); console.log(p1.name); //Kuro-P Person(); console.log(name); //Kuro-P //2.写到原型对象上,与第一种写法作用相同,只不过是不实例化时,全局中不存在对应属性 var Person = function(){ }
Person.prototype.name = ‘Kuro-P‘; Person.prototype.age = 22; Person.prototype.say = function(){ console.log(‘Hello‘); } var p2 = new Person(); console.log(p2.name); //Kuro-P Person(); console.log(name); //undefined
*注:本篇总结是基于《JavaScript高级程序设计》中第六章和《高性能JavaScript》中第二章