1. 概念
凡是对象就有原型,原型也是对象,因此凡是定义一个对象,那么就可以找到他的原型,原型还有原型,如此下去,就构成一个对象的序列,成为该结构的原型链。
2. 结构
凡是使用构造函数创建出对象,并且没有利用赋值的方式修改原型,就说该对象保留默认的原型链。
默认原型链的结构:当前对象 -> 构造函数.prototype -> Object.prototype -> null。
{} -> Object.prototype -> null;[ ] -> Array.prototype -> Object.prototype -> null。
在实现继承的时候,有时候会利用替换原型链结构的方式实现原型继承,那么原型链结构就会发生改变。
<script type="text/javascript">
function MyArr() {}
MyArr.prototype = [];
var arr = new MyArr(); // arr -> [] -> Array.prototype -> Object.prototype -> null
</script>
3. 原型式继承
利用修改原型链的结构(增加一个节点、删除一个节点、修改节点中的成员),来使得实例对象可以使用整条链中的所有成员。
<script>
function Person() {}
var p = new Person();
// 代码中{}相当于new Object(),[]相当于new Array(),/./相当于new RegExp('.')
</script>
4. 完整原型链结构
<script>
var o = {
appendTo: function(dom){}
};
function DivTag() {}
DivTag.prototype = o;
var div = new DivTag();
</script>
5. 继承
(1)最简单的继承就是将别的对象的属性强加到我的身上,那么我就有这个成员了。
(2)利用原型也可以实现继承,不需要在我的身上添加任何成员,只要原型有了,我就有了。
(3)综合:将属性、方法等成员利用混入的办法,加到构造函数的原型上,那么构造函数的实例就都具有该方法了。
<script type="text/javascript">
var Person = function() {}
Person.prototype.extend = function(o) {
for(var k in o) {
this[k] = o[k];
}
};
Person.prototype.extend({
run: function(){console.log('跑');},
eat: function(){console.log('吃');}
});
var p1 = new Person();
p1.run();
p1.eat();
console.log(new Person()); // Person{}
console.log(new Person.prototype.constructor()); // 和上面的写法完全相同
</script>
6. Object.create(对象)-> 新对象
ES5中引入的新方法,实现继承,创建一个原型继承自参数的对象。
<script type="text/javascript">
var o = {
sayHello: function(){
console.log('Hello');
}
};
var o1 = Object.create(o); // 创建新对象o1,该对象的原型即_proto_就是o
o1.sayHello();
var myArr = Object.create([]); // 创建对象,具有数组的方法,并存储数据
myArr.push(1);
// 兼容处理,如果浏览器不支持Object.create,自定义函数实现原型继承,返回的对象应该继承自obj
function inherit(obj) {
if(Object.create) { // 判断属性是否存在,区别于Object.create()方法,方法不存在即会报错
return Object.create(obj);
} else {
function F() {};
F.prototype = obj;
return new F();
}
}
var arr = inherit([]);
</script>