1、一切都是对象
一切(引用类型)都是对象,对象是属性的集合。
2、函数和对象的关系
对象是通过函数创建的(字面量的创建方式只是一种语法糖),函数也是一种对象。
3、prototype 原型
函数是一种对象,对象是属性的集合,prototype
是其中一个默认的属性。每个函数都有这个属性。
prototype
的属性值也是一个对象。
4、_proto_ (隐式原型)
每个函数都有一个 prototype
属性。每一个对象都有一个
__proto__
属性,并指向创建该对象的函数的 prototype
。
函数也是一种对象,也有 __proto__
属性,函数是被 Function
创建的。Function
是底层代码实现的。但为了原型链的统一性,有了 Function.__proto__ === Function.prototype
。
Object.prototype 是一个特例,它的 __proto__
指向是 null
。
5、原型链
访问一个对象时,先在对象本身的属性中查找,如果没有,再沿着 __proto__
这条链向上查找,直到 Object.prototype
,这就是构成了一条原型链。
6、执行上下文
在代码执行前,把将要用到的所有变量都事先拿出来,有的直接赋值,有的用 undefined
占个位。我们把代码执行前的 “准备工作” 叫做执行上下文。
全局代码的上下文环境数据内容为:
普通变量(包括函数表达式),如 var a = 10 | 声明(默认赋值为 undefined) |
函数声明,如:function fn(){} | 赋值 |
this | 赋值 |
如果代码段是函数体,那么在此基础上附加上:
参数 | 赋值 |
arguments | 赋值 |
自由变量的取值作用域 | 赋值 |
7、this
在函数中 this 到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了。因为 this 的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境。
this 一般有几种调用场景:
var obj = {
a: 1,
b: function(){console.log(this)}
}
function Fun() {
console.log(this)
}
var object = {
a: 3
}
1、作为对象调用时,指向该对象 obj.b(); // 指向obj
2、作为函数调用, var b = obj.b; b(); // 指向全局window
3、作为构造函数调用 var b = new Fun(); // this指向当前实例对象
4、作为call与apply调用 obj.b.apply(object, []); // this指向当前的object
8、执行上下文栈
执行上下文栈是用来管理执行上下文环境的。
当代码开始执行的时候,首先会把一个全局执行上下文压入执行上下文栈,在整个应用程序结束时弹出。
每当执行到一个函数时,会产生一个新的执行上下文环境,并压入执行上下文栈。当函数执行处理完成时,会将函数的执行上下文从栈中弹出。
9、作用域
ES6 之前,js 中没有块级作用域,除了全局作用域外,只有函数可以创建作用域。
作用域有上下级关系,上下级关系的确定要看函数创建的位置在哪个作用域下。
作用域最大的好处是隔离变量,不同作用域下的同名变量不会有冲突。
作用域在函数定义的时候就已经确定了(静态作用域就是这个意思),而不是在函数调用的时候确定。
在同一个作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同的变量值。所以,作用域中变量的值是在执行过程中产生确定的,而作用域却是在函数创建的时候就确定了。
10、作用域链
当查找一个变量时,会先从当前的上下文中查找,如果没有找到,就会从静态作用域的父级中查找,一直找到全局作用域,这样由每级的执行上下文的变量对象构成的链表就是作用域链。
11、自由变量
自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。在一个函数中访问一个全局变量 x,那么 x 就是一个自由变量。
12、闭包
闭包是指那些能够访问自由变量的函数。即 闭包 = 函数 + 访问自由变量
。
这里的 x,y 都是自由变量,而函数 bar 访问了它们,那么 bar 函数就是一个闭包。
var x = 1
function foo() {
var y = 2
var bar = function () {
console.log(x + y)
}
return bar
}
var f = foo()
f()
参考
http://www.cnblogs.com/wangfupeng1988/p/4001284.html
https://github.com/mqyqingfeng/Blog