Open nicoleJT914 opened 7 years ago
明明当时看的时候觉得很清楚,为什么会忘得这么快!只能重新回顾记笔记防老了。。。
在尝试把自己之前写的效果写成组件时,发现自己还是会因为作用域问题产生疑惑,在这里总结一下
词法作用域 我们在JS中提及的“作用域”一次指的是 词法作用域,词法作用域是由你把变量,函数或块作用域 定义的位置 所决定的 特别要注意的是,函数的词法作用域与 调用位置 没有关系,因为这样在代码执行时函数的词法作用域才能保持不变
动态作用域 词法作用域关注的是函数在何处声明:
function foo() { console.log( a ); // 2 } function bar() { var a = 3; foo(); } var a = 2; bar();
动态作用域关注函数在何处调用,即基于调用栈。上面代码在动态作用域下输出3 而this则具有与动态作用域相近的机制
this
应用 一个常见应用场景就是用来“隐藏内部实现”
var myOwnLibrary = { name: 'xiaoMing', doSomething: function() { // ... } }
这样暴露给外界的变量就变为myOwnLibrary的属性
myOwnLibrary
另外一种解决方式就是 模块管理 使用这些工具,任何库都无需将标识符加入到全局作用域中,而是通过依赖管理器的机制将库的标识符显式地导入到另外一个特定的作用域中。(还不了解模块管理机制,暂且将书中原话粘过来)
IIFE 函数立即执行表达式 IIFE在UMD中很常见的一种模式
var a = 2; (function IIFE( def ) { def( window ); })(function def( global ) { var a = 3; console.log( a ); // 3 console.log( global.a ); // 2 });
以上形式其实等价于
var a = 2; (function IIFE (global) { var a = 3 console.log(a) // 3 console.log(global.a) // 2 }) (window) console.log(a) // 2
只是上面是将需要执行的函数当做参数传了进去
劫持块作用域 ES6新引入的关键字let和const可以允许声明一个限制在块作用域中的变量 需要注意的是let和const不会在块作用域中进行提升
let
const
let与for循环
for (let i=0; i<10; i++) { console.log( i ); } console.log( i ); // ReferenceError
for 循环头部的let不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。这一性质在闭包中会有所体现。
for (let i=1; i<=5; i++) { setTimeout( function timer() { console.log( i ); }, i*1000 ); }
每次迭代都会重新声明i,并用上一次迭代结束时i的值来初始化。
提升这里有三点需要注意:
foo() var foo function foo() { // ... }
函数foo声明提升,变量foo声明会被忽略
明明当时看的时候觉得很清楚,为什么会忘得这么快!只能重新回顾记笔记防老了。。。
作用域
在尝试把自己之前写的效果写成组件时,发现自己还是会因为作用域问题产生疑惑,在这里总结一下
词法作用域 我们在JS中提及的“作用域”一次指的是 词法作用域,词法作用域是由你把变量,函数或块作用域 定义的位置 所决定的 特别要注意的是,函数的词法作用域与 调用位置 没有关系,因为这样在代码执行时函数的词法作用域才能保持不变
动态作用域 词法作用域关注的是函数在何处声明:
动态作用域关注函数在何处调用,即基于调用栈。上面代码在动态作用域下输出3 而
this
则具有与动态作用域相近的机制应用 一个常见应用场景就是用来“隐藏内部实现”
这样暴露给外界的变量就变为
myOwnLibrary
的属性另外一种解决方式就是 模块管理 使用这些工具,任何库都无需将标识符加入到全局作用域中,而是通过依赖管理器的机制将库的标识符显式地导入到另外一个特定的作用域中。(还不了解模块管理机制,暂且将书中原话粘过来)
IIFE 函数立即执行表达式 IIFE在UMD中很常见的一种模式
以上形式其实等价于
只是上面是将需要执行的函数当做参数传了进去
劫持块作用域 ES6新引入的关键字
let
和const
可以允许声明一个限制在块作用域中的变量 需要注意的是let
和const
不会在块作用域中进行提升let
与for循环for 循环头部的
let
不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。这一性质在闭包中会有所体现。每次迭代都会重新声明i,并用上一次迭代结束时i的值来初始化。
提升
提升这里有三点需要注意:
函数foo声明提升,变量foo声明会被忽略