一、原型
Prototype(原型)是JS为JS中函数提供的一个属性,每一个被创建出来的函数都会有这样的一个属性(箭头函数没有Prototype(原型),本文不进行讨论),我们可以通过函数名.prototype的方式访问函数的原型
function fn(){};
console.log(fn.prototype);
对象也拥有一个属性被称为__proto__(原型,这个属性是一个隐式属性,JS开发者不希望JS使用者对其做出任何的修改)
let obj = {};
console.log(obj.__proto__);
二、原型链
在JS中使用者可以通过new运算符 + 构造函数的方式实例化一个新的对象
在实例化这个新对象时JS将函数的prototype属性与新对象的__proto__属性进行关联(也可以理解为将函数的prototype赋值给新对象的__proto__)
function fn(){};
let obj = new fn();
console.log(obj.__proto__ === fn.prototype);
// 结果 true
无论是函数的prototype还是对象的__proto__它们的值都是一个对象,那么对象就需要一个构造函数进行实例化,此构造函数就是Object().然后二者的原型就会被赋值为Object.prototype
这就是最简单的原型链,当然原型链肯定是有一个尽头,不然就没完没了无限嵌套了,所以原型链的尽头就是Object.Prototype其属性值是null
let obj = {};
console.log(obj);
当使用者在对象中查找一个属性时JS会大致执行一下步骤
1. 会优先寻找对象内是否存在该属性,存在该属性则返回其属性值,不存在属性进行下一步
2. 寻找对象__proto__(原型,也就是构造函数的prototype)内是否存在该属性,存在该属性则返回其属性值,不存在属性进行下一步
3. 寻找Object.prototype内是否存在该属性,存在该属性则返回其属性值,不存在属性则返回undefined
function Fn(newName){
this.newName = newName;
};
Fn.prototype.newName = '彭于晏';
Object.prototype.newName = '刘德华';
let obj = new Fn('吴彦祖');
console.log(obj.newName);
// 结果 吴彦祖
----------------------------------------------------------
function Fn(){};
Fn.prototype.newName = '彭于晏';
Object.prototype.newName = '刘德华';
let obj = new Fn();
console.log(obj.newName);
// 结果 彭于晏
------------------------------------------------------------
function Fn(){};
Object.prototype.newName = '刘德华';
let obj = new Fn();
console.log(obj.newName);
// 结果 刘德华
在JS的规定中函数是一个可以调用的对象,所以函数也需要一个构造函数来进行实例化
const sum = new Function('a', 'b', 'return a + b');
console.log(sum(1, 2));
// 结果 3
既然函数也是一个对象那么也会__proto__指向其构造函数的prototype
既然Function.prototype是一个对象那么就需要使用构造函数Object()来进行实例化,那么Function.prototype对象的__proto__被赋值为Object.prototype