360兼容模式网站错位,039 织梦云idc网站源码,企业推广是做什么的,企业网站空间多大1. 对闭包的理解
闭包是指有权访问另一个函数作用域中变量的函数#xff0c;创建闭包的最常见的方式就是在一个函数内创建另一个函数#xff0c;创建的函数可以访问到当前函数的局部变量。
闭包有两个常用的用途#xff1b;
闭包的第一个用途是使我们在函数外部能够访问到…1. 对闭包的理解
闭包是指有权访问另一个函数作用域中变量的函数创建闭包的最常见的方式就是在一个函数内创建另一个函数创建的函数可以访问到当前函数的局部变量。
闭包有两个常用的用途
闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包可以通过在外部调用闭包函数从而在外部访问到函数内部的变量可以使用这种方法来创建私有变量。闭包的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中因为闭包函数保留了这个变量对象的引用所以这个变量对象不会被回收。
比如函数 A 内部有一个函数 B函数 B 可以访问到函数 A 中的变量那么函数 B 就是闭包。
function A() {let a 1window.B function () {console.log(a)}
}
A()
B() // 1在 JS 中闭包存在的意义就是让我们可以间接访问函数内部的变量。经典面试题循环中使用闭包解决 var 定义函数的问题
for (var i 1; i 5; i) {setTimeout(function timer() {console.log(i)}, i * 1000)
}首先因为 setTimeout 是个异步函数所以会先把循环全部执行完毕这时候 i 就是 6 了所以会输出一堆 6。解决办法有三种
第一种是使用闭包的方式
for (var i 1; i 5; i) {(function (j) {setTimeout(function timer() {console.log(j)}, j * 1000)})(i)
}在上述代码中首先使用了立即执行函数将 i 传入函数内部这个时候值就被固定在了参数 j 上面不会改变当下次执行 timer 这个闭包的时候就可以使用外部函数的变量 j从而达到目的。
第二种就是使用 setTimeout 的第三个参数这个参数会被当成 timer 函数的参数传入。
for (var i 1; i 5; i) {setTimeout(function timer(j) {console.log(j)},i * 1000,i)
}第三种就是使用 let 定义 i 了来解决问题了这个也是最为推荐的方式
for (let i 1; i 5; i) {setTimeout(function timer() {console.log(i)}, i * 1000)
}2. 对作用域、作用域链的理解
1全局作用域和函数作用域
1全局作用域
最外层函数和最外层函数外面定义的变量拥有全局作用域所有未定义直接赋值的变量自动声明为全局作用域所有window对象的属性拥有全局作用域全局作用域有很大的弊端过多的全局作用域变量会污染全局命名空间容易引起命名冲突。
2函数作用域
函数作用域声明在函数内部的变零一般只有固定的代码片段可以访问到作用域是分层的内层作用域可以访问外层作用域反之不行
2块级作用域
使用ES6中新增的let和const指令可以声明块级作用域块级作用域可以在函数中创建也可以在一个代码块中的创建由{ }包裹的代码片段let和const声明的变量不会有变量提升也不可以重复声明在循环中比较适合绑定块级作用域这样就可以把声明的计数器变量限制在循环内部。
作用域链 在当前作用域中查找所需变量但是该作用域没有这个变量那这个变量就是自由变量。如果在自己作用域找不到该变量就去父级作用域查找依次向上级作用域查找直到访问到window对象就被终止这一层层的关系就是作用域链。
作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问通过作用域链可以访问到外层环境的变量和函数。
作用域链的本质上是一个指向变量对象的指针列表。变量对象是一个包含了执行环境中所有变量和函数的对象。作用域链的前端始终都是当前执行上下文的变量对象。全局执行上下文的变量对象也就是全局对象始终是作用域链的最后一个对象。
当查找一个变量时如果当前执行环境中没有找到可以沿着作用域链向后查找。
3. 对执行上下文的理解
1. 执行上下文类型
1全局执行上下文
任何不在函数内部的都是全局执行上下文它首先会创建一个全局的window对象并且设置this的值等于这个全局对象一个程序中只有一个全局执行上下文。
2函数执行上下文
当一个函数被调用时就会为该函数创建一个新的执行上下文函数的上下文可以有任意多个。
3eval函数执行上下文
执行在eval函数中的代码会有属于他自己的执行上下文不过eval函数不常使用不做介绍。
2. 执行上下文栈
JavaScript引擎使用执行上下文栈来管理执行上下文当JavaScript执行代码时首先遇到全局代码会创建一个全局执行上下文并且压入执行栈中每当遇到一个函数调用就会为该函数创建一个新的执行上下文并压入栈顶引擎会执行位于执行上下文栈顶的函数当函数执行完成之后执行上下文从栈中弹出继续执行下一个上下文。当所有的代码都执行完毕之后从栈中弹出全局执行上下文。
let a Hello World!;
function first() {console.log(Inside first function);second();console.log(Again inside first function);
}
function second() {console.log(Inside second function);
}
first();
//执行顺序
//先执行second(),在执行first()3. 创建执行上下文
创建执行上下文有两个阶段创建阶段和执行阶段
1创建阶段
1this绑定
在全局执行上下文中this指向全局对象window对象在函数执行上下文中this指向取决于函数如何调用。如果它被一个引用对象调用那么 this 会被设置成那个对象否则 this 的值被设置为全局对象或者 undefined
2创建词法环境组件
词法环境是一种有标识符——变量映射的数据结构标识符是指变量/函数名变量是对实际对象或原始数据的引用。词法环境的内部有两个组件加粗样式环境记录器:用来储存变量个函数声明的实际位置外部环境的引用可以访问父级作用域
3创建变量环境组件
变量环境也是一个词法环境其环境记录器持有变量声明语句在执行上下文中创建的绑定关系。
2执行阶段 此阶段会完成对变量的分配最后执行完代码。
简单来说执行上下文就是指
在执行一点JS代码之前需要先解析代码。解析的时候会先创建一个全局执行上下文环境先把代码中即将执行的变量、函数声明都拿出来变量先赋值为undefined函数先声明好可使用。这一步执行完了才开始正式的执行程序。
在一个函数执行之前也会创建一个函数执行上下文环境跟全局执行上下文类似不过函数执行上下文会多出this、arguments和函数的参数。
全局上下文变量定义函数声明函数上下文变量定义函数声明thisarguments