原型:
1.每个对象都有一个__proto__属性,该属性指向该对象的构造函数的原型; 如:
let obj = {};
obj.__proto__ === Object.prototype//true
2.每个函数都有一个prototype属性,该属性指向原型,如:
let fn = ()=>{};
fn.__proto__ === Function.prototype//true
原型链:
当一个对象的构造函数的原型对象被更改指向另一个类型的实例时,两者的原型对象则形成一条原型链。
更改指针指向时,会新实例会继承另一个类型的实例的构造函数的属性,因此当在一个对象找不到某个属性时,会去原型链上找,一层层往上找,一直找不到,则是undefined
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假设我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个圆形中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。
--摘自《javascript高级程序设计》
查看原型
1.浏览器提供的方法:
obj.__proto__
2.ES5提供的方法:
Object.getPrototypeOf(obj)
函数原型:
其他与对象的原型一样,因为函数也是对象,所以它也有[[prototype]]隐式原型,故:
function foo(){}
console.log(foo.__proto__)//可行
又因为是函数,所以会多出来一个显示原型:prototype,因此存在这么一个结论
foo.__proto__ === foo.prototype
注意:声明函数有 函数表达式的方式、有 函数声明的方式,
//函数表达式方式:
const fooA = function(){};
//函数声明的方式:
function fooB(){}
因为函数声明可以提前被解析成函数,而表达式不可以,因此:
fooA.__proto__ === fooA.prototype//false;
fooB.__proto__ === fooB.prototype//true;