javascript原型和原型链

一、原型规则

1、所有的引用类型(数组、对象、函数)都具有对象特性,即可自由扩展属性(除了“null”)

var array=[];array.a=1;
var object={};object.a=1;
function func(){};
func.a=1;

2、所有的引用类型(数组、对象、函数)都有一个__proto__属性(隐式原型属性),属性值是一个普通的对象

console.log(array.__proto__);
console.log(object.__proto__)
console.log(func.__proto__)

3、所有的函数,都有一个 prototype(显式原型)属性,属性值也是一个普通的对象

console.log(func.prototype)

4、所有的引用类型(数组、对象、函数),__ proto__(隐式原型)属性值指向它的构造函数的“prototype”属性值

console.log(array.__proto__===Array.prototype);  //true
console.log(object.__proto__===Object.prototype);  //true
console.log(func.__proto__===Function.prototype);  //true

5、当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_(即它的构造函数的 prototype(显式原型))中寻找

function Person(){};
Person.prototype.name = "小明";
var p1 = new Person();
var p2 = new Person();
p1.name="小红"
console.log(p1.name); // 小红 来自实例
console.log(p2.name); // 小明 来自原型

二、原型链

原型链是实现继承的主要方法。
原型链的思路:
查找属性,如果本身没有,则会去__proto__中查找,也就是构造函数的显式原型中查找,如果构造函数中也没有该属性,因为构造函数也是对象,也有__proto__,那么会去它的显式原型中查找,一直到null,如果没有则返回undefined。

举一个比较典型的例子:

Function.prototype.a = "a";
Object.prototype.b = "b";
function Person(){}
let p = new Person();
console.log(p);         //Person {} 
console.log(p.a);       //undefined
console.log(p.b);       //b

可能有人会有疑问,为什么p没有继承Function原型里面的属性,其实Person()才是Function对象的一个实例,new Person()返回来的是一个对象,是Object的一个实例,没有继承Function,无法访问Function原型的属性。

console.log(Person.__proto__===Function.Prototype)  //true

按照思路进行查找:

console.log(p.__proto__)   //返回Person.prototype
console.log(p.__proto__.__proto__) //返回Object.prototype

所以p.b打印结果为b,p没有b属性,会一直通过__proto__向上查找,最后当查找到Object.prototype时找到,最后打印出b,向上查找过程中,得到的是Object.prototype,而不是Function.prototype,找不到a属性,所以结果为undefined,这就是原型链,通过__proto__向上进行查找,最终到null结束(Object.prototype.__ proto__===null)。

顺便一提,js里面所有的对象都是Object的实例,Person()函数也是可以访问到Object原型的属性。

console.log(Person.b)  //b

最后盗张图帮助理解
javascript原型和原型链_第1张图片

你可能感兴趣的:(javascript,js,javascript)