原因是每个对象都有 __proto__ 属性,此属性指向该对象的构造函数的原型。
对象可以通过 __proto__ 与上游的构造函数的原型对象连接起来,⽽上游的原型对象也有⼀个 __proto__ ,
这样就形成了原型链。
通过原型继承的⽅法并不是⾃身的,我们要在原型链上⼀层⼀层的查找,
这样创建的好处是只在内存中创建⼀次,实例化的对象都会指向这个 prototype 对象。
Player.prototype ={
start:function(){ console.log("下棋"); },
revert:function(){ console.log("悔棋"); },
};
⾯向对象的特点是什么?
封装:让使⽤对象的⼈不考虑内部实现,只考虑功能使⽤把内部的代码保护起来,
只留出⼀些 api 接⼝供⽤户使⽤;
继承:就是为了代码的复⽤,从⽗类上继承出⼀些⽅法和属性,⼦类也有⾃⼰的⼀些属性;
多态:是不同对象作⽤于同⼀操作产⽣不同的效果。多态的思想实际上是把“想做什么”和“谁去做“分开;
原型链⼜是什么呢?
我们都知道当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,
就去找原型的原型,⼀直找到最顶层为⽌。举个例⼦
function Player(){}
Player.prototype.name ="Kevin";
var p1 =newPlayer();
p1.name ="Daisy";// 查找p1对象中的name属性,因为上⾯添加了name,所以会输出“Daisy”
console.log(p1.name);// Daisy
delete p1.name;// 删除了p1.name,然后查找p1发现没有name属性,就会从p1的原型p1.__proto__中去找,
也就是Player.prototype,然后找到了name,输出"Kevin"
console.log(p1.name);// Kevin
那如果我们在 Player.prototype 中也找不到 name 属性呢,那么就会去 Player.prototype.proto中去寻找,也就是{}。
Object.prototype.name ="root";
function Player(){}
Player.prototype.name ="Kevin";
var p1 =newPlayer();
p1.name ="Daisy";// 查找p1对象中的name属性,因为上⾯添加了name,所以会输出“Daisy”
console.log(p1.name);// Daisy
delete p1.name;// 删除了p1.name,然后查找p1发现没有name属性,就会从p1的原型p1.__proto__中去找,
也就是Player.prototype,然后找到了name,输出"Kevin"
console.log(p1.name);// Kevin
delete Player.prototype.name;
console.log(p1.name);
这样⼀条通过proto和 prototype 去连接的对象的链条,就是原型链