函数的prototype属性:
- prototype属性是每一个函数都具有的属性,但是不是一个对象都具有的属性。
- 它默认指向一个object空对象(即成为原型对象)
- 原型对象中有一个constructor属性,该属性又指向该函数,也就是说
function fun(){
};
fun.prototype 就是指向原型对象
fun.prototype.constructor 就是原型对象的constructor属性
consolo.log(fun.prototype.constructor === fun); // true
// 就是fun函数的原型对象的constructor属性又指向fun函数
// 形成一个闭环
图解:
这里的含义就是:type函数的prototype属性指向它的原型对象(type.prototype表示原型对象);而type函数的原型对象的constructor属性又指向type函数,形成一个闭环。
显示原型属性和隐式原型属性
每个函数的prototype属性,显示原型属性
每个实例对象都有proto属性,隐式原型属性
实例对象的隐式原型proto 等于 构造函数的显式原型prototype
function Fun(){};
let f = new Fun();
// 函数的prototype属性,显示原型属性
console.log(Fun.prototype)
// 实例对象都有__proto__属性,隐式原型属性
console.log(f.__proto__)
// 对象的隐式原型(__proto__)指向创建它的构造函数的显示原型(prototype)
console.log(f.__proto__ === Fun.prototype) // true
proto隐式原型和prototype显式原型其实都是引用类型,都指向的是函数的原型对象。引出原型链
图:实例都是通过proto,去一级一级查找
原型链
原型和原型链的关系,首先要明确一下几个概念:
- JS中的所有东西都是对象,函数也是对象, 而且是一种特殊的对象
- JS中所有的东西都由Object衍生而来, 即所有东西原型链的终点指向Object.prototype
- JS对象都有一个隐藏的proto属性,他指向创建它的构造函数的原型,但是有一个例外,Object.prototype.proto指向的是null(原型链的尽头)。
访问一个对象的属性时:(别名:隐式原型链)
- 先在自身属性查找,找到并返回
- 如果没有,沿着自身的proto这条链上查找,找到并返回
- 最后查找到null时,返回undefined
构造函数本身又是方法(Function)的实例, 因此也可以查到它的proto(原型链)
function Foo(){}
// 等价于
var Foo= new Function();
// 而Function实际上是
function Function(){ Native Code}
// 也就是等价于
var Function= new Function();
所以说Function是通过自己创建出来的。正常情况下对象的proto是指向创建它的构造函数的prototype的.所以Function的proto指向的Function.prototype
Object 实际上也是通过Function创建出来的
typeof(Object) // function
// so
function Object(){
Native Code
}
// 等价于
var Object = new Function();
// Object的__proto__指向的是Function.prototype,也即是
Object.__proto__ === Function.prototype //true
下面再来看Function.prototype的proto指向哪里?
因为JS中所有的东西都是对象,那么,Function.prototype 也是对象,既然是对象,那么Function.prototype肯定是通过Object创建出来的,所以:
Function.prototype.__proto__ === Object.prototype //true
// 最终
Object.prototype.__proto__ === null
- 读取对象的属性时,会自动到原型链中查找。
- 设置对象属性或方法时,不会查找原型链,如果当前对象没有此属性,直接添加此属性
- 方法一般定义在Fn.prototype原型对象中,方面继承