原创声明:本文除了标明引用的内容外,都为本人原创,请尊重本人的知识产权,不能用于商业用途。欢迎转载,转载请在文章开头处插入以下内容:
本文转载自"狂龙ing”的Blog,地址为“http://blog.csdn.net/kuanglong2016/article/details/17549055"
背景知识
ECMAScript中有5种基本数据类型:Undefined、Null、Boolean、Number和String。还有1种复杂数据类型——Object(对象),ECMAScript不支持任何创建自定义类型的机制,而所有值最终都将是上述6种数据类型之一(参见“JavaScript高级程序设计(第3版)”)。在ECMAScript中,
函数也是对象。
ECMAScript是一种语言标准,JavaScript则是ECMAScript的一种实现,并提供了浏览器和网络相关的一些特性。下面统一使用JavaScript来描述。
概念和原理
JavaScript是一种原型语言,所有的对象都有一个原型(Prototype Link或 Hidden Link),对象通过一个叫做[[Prototype]]的“指针”指向其原型。虽然在脚本中没有标准的方式访问[[Prototype]],但Firefox、Safari和Chrome在每个对象上都支持一个属性__proto__,作为[[Prototype]]的实现。所以在这些浏览器中,对象可以通过的__proto__来访问其原型。
原型可以为对象提供额外的属性或方法,类似于Java或C++中的父类,但JavaScript中的原型是一种动态绑定,而且是”对象继承”不是“类继承”,原型对象所做的任何修改都能够立即从实例对象上反映出来。
原型详解
这里首先需要特别强调JavaScript的两个特点:
1. 所有对象都有原型对象,包括字面量对象、函数以及构造函数生成的对象;
2. 对象的原型也是对象,所以也有其自己的原型对象,根据原型链一直延伸,最后都指向Object.prototype,而Object.prototype的原型为Null。
1. 字面量对象:原型为Object.prototype
var person = {
"First_Name": "Barry",
"Last_Name": "Steyn",
"do_Something": function() { alert('something'); }
}
修改原型Object.prototype可以增强字面量对象
person.age; // undefined - property age does not exist
Object.prototype.age = 56; // Every object is linked to Object.prototype by default
person.age; // 56
2. 函数:所有函数都是对象 ,其原型为Function.prototype。需要注意的是:不要混淆函数prototype属性和其原型。每个函数都有prototype属性,每个对象(函数也是对象)都有原型。
function foo(){
console.log('foo');
}
foo.__proto__ == Function.prototype; //True
var bar = function(){
console.log('bar');
}
bar.__proto__ == Function.prototype; //True
var person = {
name: "person name",
show: function(){
console.log(this.name);
}
}
person.show.__proto__ == Function.prototype; //True
可以通过修改原型Function.prototype来增强所有函数
Function.prototype.subtract= function(num1, num2){
return num1 - num2;
};
foo.subtract(20, 3); //17
3. 构造函数生成的对象,其原型为其构造函数的prototype
var Animal = function(name) {
this.name = name;
}
var cat = new Animal('fluffy'); //Using new to invoke the function
cat.__proto__ == Animal.prototype; //True
a) Animal是一个对象(因为所有函数都是对象),其原型是Function.prototype
b) Animal是函数,所以有一个prototype属性
c) cat也是一个对象,由Animal函数构造出来,是对象就有原型,其原型与字面量对象不同,不是Object.prototype而是Animal.prototype
这里问一个问题:Animal.prototype的原型是什么? 当然就是Object.prototype
特别需要注意的有:
Object.__proto__ == Function.__proto__ == Function.property, 因为Object和Function都是函数
Object函数构造的对象的原型是Object.prototype
功能作用
使用原型可以实现非常灵活的继承,比如Douglas Crockford提出的原型式继承
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var pussy_cat = object(cat);
pussy_cat.__proto__ == cat; //True
总结
字面量对象: 原型 == Object.prototype
函数: 原型 == Function.prototype
构造函数生成对象:
原型 == [Constructor].prototype