原型
显式原型和隐式原型
- 每一个函数都有一个prototype属性,即显式原型,指向一个空的Object对象。
- 每一个实例对象都有一个__proto__属性,即隐式原型,隐式原型的值为其对应的构造函数的显式原型的值。
function Fn(){}
console.log(Fn.prototype);
var fn = new Fn();
console.log(fn.__proto__);
console.log(Fn.prototype===fn.__proto__); //true
原型链
在访问对象的属性(方法)时先在自身属性中查找,如果没有找到就沿着__proto__这条链往上查找,如果没有找到则返回undefined。
原型链的简单图形说明:
图像说明:
- Fn.prototype指向Fn原型对象,Fn原型对象的__proto__指向Object的原型对象。
- Object()是内置的函数,Object.prototype同样指向一个Object原型对象,但这个原型对象的__proto__为null,是原型链的尽头。
- 使用原型链时:从实例的__proto__开始往上找直到找到Object原型对象发现__proto__为null时结束。如果前面找到了即返回相应值。
进一步的图形说明:
在这里插入图片描述
注意
- 函数的显示原型指向的对象默认是空Object实例对象(但Object不满足);
- 所有函数都是Function的实例(包含Function);
- Object的原型对象是原型链尽头
说明:
- Function来源于:
Function = new Function()
(通过new自身产生的实例),自身的隐式原型等于构造函数的显式原型即自身的显式原型,因此Function.prototype === Function.__proto__
为true。 - 因为所有的函数都是Function的实例,所以所有函数的__proto__指向的都是Function的prototype。
instanceof
表达式: A instanceof B,如果B函数的显式原型对象在A对象的原型链上, 返回true, 否则返回false。
console.log(Object instanceof Function) // true
console.log(Object instanceof Object) // true
console.log(Function instanceof Function) // true
console.log(Function instanceof Object) // true
练习:
function A () {}
A.prototype.n = 1
var b = new A()
//直接将一个新的对象赋给A.prototype,并不影响b,b.__proto__指向的仍然是开始的那个A.prototype对象
A.prototype = {
n: 2,
m: 3
}
var c = new A()
console.log(b.n, b.m, c.n, c.m) //1,undefined,2,3
执行上下文
全局上下文
在执行全局代码前将window确定为全局执行上下文
函数上下文
在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象(虚拟的, 存在于栈中)。ps:定义函数并不会出现函数上下文,调用时才出现
执行上下文栈
在全局代码执行前, JS引擎就会创建一个栈来存储管理所有的执行上下文对象,当全局执行上下文确定后就将其添加到栈中,在函数执行上下文创建后, 将其添加到栈中。在当前函数执行完后,将栈顶的对象移除。当所有的代码执行完后, 栈中只剩下window。
练习
var c = 1
function c(c) {
console.log(c)
var c = 3
}
c(2) // 报错
相当于执行
var c
function c(c) {
var c
console.log(c)
c = 3
}
c = 1 //c变为了number型
c(2)