原型和闭包
每个函数都有一个属性prototype ,其属性值是一个对象,默认只有一个叫constructor 的属性,指向这个函数本身
每个对象都有一个隐藏的__proto__ 属性,指向创建这个对象的函数的prototype
Object.prototype.__proto__ ===null
函数也是对象,也有__proto__ Object.__proto__ ===Function.prototype
Function 也是一个函数,是一种对象,有__proto__ 属性,它一定是被Function 创建,所以Function 是被自身创建,它的__proto__ 指向自身的prototype
Function.prototype.__proto__ ===Object.prototype
Function.prototype 所指向的对象也是被Object 创建的对象
instanceof 运算符
第一个参数是一个对象A,第二个对象是一个函数B
规则:沿着A的__proto__ 这条线来查找,同时沿着B的prototype 这条线来查找,当两条线查找到同一个引用时,说明为同一对象,返回true ,如果到终点还没找到,返回false
instanceof 代表一种继承关系,或者原型链的结构
JavaScript 继承通过原型链体现:访问一个对象的属性时,先在对象自身的属性中查找,如果没有找到再沿着__proto__ 查找其构造函数上是否有该属性.
hasOwnproperty() 判断是否是自身的属性,从Object.prototype 中来
所有对象的原型链都会找到Object.prototype
执行上下文环境
变量先定义再赋值,也就是变量赋值是在赋值语句执行时进行的.
var a;
a = 100;
对于函数来说
在准备阶段,需要完成一下工作,以下数据的准备情况称之为执行上下文
全局代码的执行上下文
数据 | 完成工作 |
---|
变量,函数表达式 | 变量的声明,默认赋值为undefined | this | 赋值 | 函数声明 | 赋值 | | |
函数体代码,在上面基础下附加以下内容
数据 | 完成工作 |
---|
参数 | 赋值 | arguments | 赋值 | 自由变量的取值作用域 | 赋值 |
在执行代码之前,把将要用到的所有的变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。
this 的指向情况
| |
---|
普通函数和全局环境下 | window | 构造函数 | 实例化的对象 | 对象的方法 | 指向对象,如果方法赋值给一个变量,则指向window | call或apply | 执行传入的对象 | 定时器 | window | 立即执行函数 | window | 事件绑定函数 | 绑定的事件对象 |
普通函数的内部定义的函数this 也指向全局对象window
作用域和执行上下文环境
执行全局代码时,会产生一个全局作用域Global ,每次调用函数时,又会产生执行上下文环境Local ,当函数调用完成时,这个上下文环境和数据都会被清除,再回到全局上下文环境Global ,处于活动中的上下文环境只有一个.
切换执行上下文环境的过程称为入栈和出栈(执行上下文栈 )
作用域最大的作用是隔离变量
-
函数每次被调用都会产生一个新的执行上下文环境 -
作用域中没有变量,要通过作用域对应的执行上下文环境来获取变量值 -
同一个作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同的变量值. -
作用域中变量值是在执行过程产生并确定的,而作用域是在函数创建的时候就已经确定了
所以,要查找一个作用域下某个变量的值,就要找到这个作用域下对应的执行上下文环境,再在其中查找变量值.
自由变量:在A作用域中使用变量x,但没有在A作用域中声明,即x是在其他作用域中声明的,对于A来说,x就是一个自由变量
函数中自由变量的取值要到创建这个函数的作用域中去取
闭包应用
-
函数作为返回值 function fn() {
var max = 10;
return function bar(x) {
if(x > max) {
console.log(x);
}
}
}
var f1 = fn();
f1(15)
bar 函数作为返回值,赋值给变量f1 ,执行f1(15) 时,用到了fn 作用域下的max 变量的值 -
函数作为参数传递 var max = 10;
fn = function (x) {
if(x > max) {
console.log(x);
}
};
(function (f) {
var max = 100;
f(15);
})(fn);
fn 函数作为参数传递进另外一个函数,赋值给f 参数,执行f(15) 时,max 的取值是10
|