作用域
事实上JavaScript并不具有动态作用域,它只有词法作用域,简单明了,但是this机制某种程度上很像动态作用域
词法作用域
是一套引擎如何寻找变量以及会在何处找到变量的规则,它是定义在词法阶段的作用域,是由写代码时将变量和块作用域写在哪里来决定的。
动态作用域
动态作用域并不关心函数和作用域是如何声明以及在何处声明的,只关心它们从何处调用。类似this的指向问题。
作用域链
A(B(C{ console.log(xxx)})) A中有B,B中有C。则C中打印xxx变量的时候会向上找直到找到第一个匹配的为止,否则返回undefind
原型
在JavaScript中,每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype
属性,这个属性指向函数的原型对象,并且这个属性是一个对象数据类型的值。
让我们用一张图表示构造函数和实例原型之间的关系:
image
原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中。
相当于java类中的static 变量
原型链
调用属性,会顺着属性原型链一直查找。
function Person() {}
Person.prototype.a = 123;
Person.prototype.sayHello = function () {
alert("hello");
};
var person = new Person()
console.log(person.a)//123
console.log(person.hasOwnProperty('a'));//false
console.log('a'in person)//true
person实例中没有a这个属性,从 person 对象中找不到 a 属性就会从 person 的原型也就是 person.__proto__
,也就是 Person.prototype中查找,很幸运地得到a的值为123。那假如 person.__proto__
中也没有该属性,又该如何查找?
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层Object为止。Object是JS中所有对象数据类型的基类(最顶层的类)在Object.prototype上没有__proto__
这个属性。
console.log(Object.prototype.__proto__ === null) // true
闭包
闭包是通过改变JS回收机制保留某段作用域的一种手段。当一个函数执行完毕后,里面的局部变量是会被JS自带的垃圾回收机制给销毁的,从而释放内存。但是如果返回一个函数,而且函数里面有用到父级数声明的变量,那么此时,变量不会被回收,因为还有可能被用到,并且外界可以通过函数访问这段作用域下的变量。
闭包的作用:
xxx
执行上下文
参考 https://www.cnblogs.com/wilber2013/p/4909430.html
JavaScript解释器会创建执行上下文 Execution Context,其实这里会有两个阶段:
-
创建阶段(当函数被调用,但是开始执行函数内部代码之前)
- 创建 作用域链 Scope chain
- 创建 变量对象 VO/AO(variables, functions and arguments)
- 设置this的值
-
激活/代码执行阶段
- 设置变量的值、函数的引用,然后解释/执行代码