JavaScript是一门动态语言, 你能够在任什么时候候向对象上添加属性,以下浏览器
function Student() { this.name = 'LeBron James'; this.gender = 'Male'; } var studObj1 = new Student(); studObj1.age = 15; alert(studObj1.age); // 15 var studObj2 = new Student(); alert(studObj2.age); // undefined
正如上面的实例, age
属性附加在 studObj1
实例上. 然而 studObj2
实例没有这个属性, 由于 age
属性只在 studObj1
实例上定义了.函数
那么, 若是想在后期添加一个属性且能被全部的实例所共享, 该怎么办? 答案这就今天主角 Prototype
.工具
Prototype
是一个对象, 默认状况下与JavaScript中的任何一个函数或对象有关, 只是惟一区别在于函数的prototype
属性是可访问
和可修改
的,而对象
的prototype
属性是不可见的.this
默认状况下任何一个函数包含 Prototype
对象, 以下图:spa
prototype
对象是一种特殊类型的可枚举对象, 能够将须要附加属添加到其上,这些属性将在其构造函数的全部实例之间共享。prototype
所以, 把上面的示例中使用函数的 prototype
来添加属性,以便于全部对象中均可以访问到, 以下:3d
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } Student.prototype.age = 15; var studObj1 = new Student(); alert(studObj1.age); // 15 var studObj2 = new Student(); alert(studObj2.age); // 15
使用 字面量
或 经过 new关键字和构造函数
的方式建立的每个对象都包含 __proto__
属性, 该属性指向建立此对象的函数的 原型对象
.调试
你能够在谷歌和火狐开发者调试工具中查看该属性(__proto__
) , 根据下面的示例:code
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } var studObj = new Student(); console.log(Student.prototype); // object console.log(studObj.prototype); // undefined console.log(studObj.__proto__); // object console.log(typeof Student.prototype); // object console.log(typeof studObj.__proto__); // object console.log(Student.prototype === studObj.__proto__ ); // true
正如上面例子看到, 函数经过 [[函数名称]].prototype
方式访问到原型对象. 可是, 对象(实例)并无暴露出 prototype
属性,而是使用 __proto__
来访问它.对象
前面说起到, 原型对象在对象中是不可见. 使用 Object.getPrototypeOf(obj)
方法来访问实例的原型对象. (这也是推荐方式, __proto__
并非标准属性, 在IE11如下其它浏览器中没有实现).
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } var studObj = new Student(); Student.prototype.sayHi= function(){ alert("Hi"); }; var studObj1 = new Student(); var proto = Object.getPrototypeOf(studObj1); // returns Student's prototype object alert(proto.constructor); // returns Student function
Object 原型对象包含以下 属性
和 方法
属性 | 描述 |
---|---|
constructor |
返回建立该实例的构造函数 |
__proto__ |
指向建立该实例的构造函数的原型对象. |
方法 | 描述 |
---|---|
hasOwnProperty() |
返回一个布尔值,指示对象是否包含指定的属性做为该对象的直接属性,而不是经过原型链继承。 |
isPrototypeOf() |
返回一个布尔值,指示指定的对象是否位于调用此方法的对象的原型链中。 |
propertyIsEnumerable() |
返回一个布尔值,该布尔值指示指定的属性是否可枚举。 |
toLocaleString() |
返回本地格式的字符串. |
toString() |
返回对象字符串形式. |
valueOf() |
返回指定对象的原始值. |
Chrome 和 Firfox 将对象的原型表示为 __proto__
, 而内部引用为 [[Prototype]]
. IE不支持,只有IE11
包含它.
如上所述, 每一个对象都能连接到函数的原型对象. 若是您更改了函数的原型, 则只有新对象将连接到更改后的原型. 全部其余现有对象仍然连接到旧的函数原型. 下面实例来演示这个场景:
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } Student.prototype.age = 15; var studObj1 = new Student(); alert('studObj1.age = ' + studObj1.age); // 15 var studObj2 = new Student(); alert('studObj2.age = ' + studObj2.age); // 15 Student.prototype = { age : 20 }; var studObj3 = new Student(); alert('studObj3.age = ' + studObj3.age); // 20 alert('studObj1.age = ' + studObj1.age); // 15 alert('studObj2.age = ' + studObj2.age); // 15
原型对象被JavaScript引擎用来作两件事:
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } Student.prototype.sayHi = function(){ alert("Hi"); }; var studObj = new Student(); studObj.toString();
在上面的示例, toString()
方法在 Student
中没有定义, 那么它是如何以及从哪里找到 toString()
的呢?
在这里,原型出现了. 首先, JavaScript 引擎检查 studObj 是否存在 toString
方法?. 若是没有找到,那么它使用 studObj
的 __proto__
连接指向 Student函数
的 原型对象
. 若是它仍然没法找到它那么它会在往上层并检查 Object 函数的原型对象,由于全部对象都是从 JavaScript 中的 Object 派生的,并查找 toString()
方法. 所以, 它在Object函数的原型对象中找到 toString()
方法,所以咱们能够调用 studObj.toString()
.
查找方式,以下图所示
上述就是原型基本知识点以及应用.