原型与原型链 prototype和_proto__
原型与原型链
- 所有函数都有一个特别的属性:
prototype
:显示原型属性
- 所有实例对象都有一个特别的属性
__proto__
:隐式原型属性
- 显示原型和隐式原型的关系
- 函数的prototype:定义函数时被自动赋值。值默认为{},即为原型对象。
- 实例对象的proto,在创建实例对象时被自动添加,并赋值为构造函数的prototype值。
- 原型对象即为当前实例对象的父对象。
- 原型链
- 所有的实例对象都有proto属性,它指向的就是原型对象
- 这样通过proto属性就形成了一个链的结构—>原型链
- 当查找对象内部的属性/方法时,js引擎自动沿着这个原型链查找
- 当给对象属性赋值时,不会使用原型链,而只是在当前对象中进行操作
函数的prototype属性(图)
- 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象)
- 原型对象中有一个属性constructor, 它指向函数对象
<script>
// 每一个函数都有一个prototype属性,他默认指向一个object空对象(即为:原型对象)
console.log(Date.prototype,typeof Date.prototype);
</script>
function Fun () {
}
console.log(Fun.prototype) // 默认指向一个Object空对象(没有我们的属性)
// 原型对象中有一个属性constructor, 它指向函数对象
console.log(Date.prototype.constructor===Date)
console.log(Fun.prototype.constructor===Fun)
// 给原型对象添加属性(一般是方法)===>实例对象可以访问
Fun.prototype.test = function () {
console.log('test()');
}
console.log(Fun.prototype);
var fun = new Fun();
fun.test();
显示原型与隐式原型
-
每一个函数function都有一个
prototype
,即显示原型 -
每一个实例对象都有一个
__proto__
,可称为隐式原型 -
对象的隐式原型的值为其对应构造函数的显示原型的值
-
内存结构
-
总结:
- 函数的
prototype
属性:在定义函数时自动添加,默认是一个空的Object对象 - 对象的
__proto__
属性:在创建对象时自动添加的,默认值为构造函数的prototype的属性值 - 程序员能直接操作显示原型,但是不能直接操作隐式原型(ES6之前)
- 函数的
-
<script type="text/javascript"> //定义构造函数 function Fn() { // 内部语句: this.prototype = {} } // 1. 每个函数function都有一个prototype,即显式原型属性, 默认指向一个空的Object对象 console.log(Fn.prototype) // 2. 每个实例对象都有一个__proto__,可称为隐式原型 //创建实例对象 var fn = new Fn() // 内部语句: this.__proto__ = Fn.prototype console.log(fn.__proto__) // 3. 对象的隐式原型的值为其对应构造函数的显式原型的值 console.log(Fn.prototype===fn.__proto__) // true //给原型添加方法 Fn.prototype.test = function () { console.log('test()') } //通过实例调用原型的方法 fn.test() </script>
原型链(图解)
* 访问一个对象的属性时, * 先在自身属性中查找,找到返回 * 如果没有, 再沿着__proto__这条链向上查找, 找到返回 * 如果最终没找到, 返回undefined * 别名: 隐式原型链 * 作用: 查找对象的属性(方法)
/*
1. 函数的显示原型指向的对象默认是空Object实例对象(但Object不满足)
*/
console.log(Fn.prototype instanceof Object) // true
console.log(Object.prototype instanceof Object) // false
console.log(Function.prototype instanceof Object) // true
/*
2. 所有函数都是Function的实例(包含Function)
*/
console.log(Function.__proto__===Function.prototype)
/*
3. Object的原型对象是原型链尽头
*/
console.log(Object.prototype.__proto__) // null
原型链属性问题
1. 读取对象的属性值时: 会自动到原型链中查找
2. 设置对象的属性值时: 不会查找原型链, 如果当前对象中没有此属性, 直接添加此属性并设置其值
3. 方法一般定义在原型中, 属性一般通过构造函数定义在对象本身上