js面试题——作用域和闭包
作用域和自由变量
作用域
-
作用域:变量的合法使用范围
-
全局作用域:在全局可以使用
-
函数作用域:只能在函数块中使用
-
块级作用域(ES6新增):let,const定义的变量有块级作用域{}内部使用
自由变量:
-
一个变量在当前作用域没有定义,但是被使用了
-
向上级作用域,一层一层一次寻找,知到找到为止
-
闭包
闭包:所有自由变量的查找,是在函数定义的地方,向上级作用域查找
不是在函数执行的地方查找。
闭包是作用域应用的特殊情况,有两种表现:
-
函数作为参数被传递
-
函数作为返回值被返回
// 函数作为返回值 function create(){ let a = 100 return function(){ console.log(a) } } let fn = create() let a = 200 fn()
// 函数作为函数 function print(fn){ let a = 200 fn() } let a = 100 function fn(){ console.log(a) } print(fn)
this 在各个场景中取什么样的值,是在函数执行的时候确定的,不是在函数定义时确定的。
this 的应用场景
-
作为普通函数被调用
-
使用 call apply bind 调用
-
作为对象方法被调用
-
在 class 方法中调用
-
箭头函数
1.this的不同应用场景,如何取值?
-
当作普通函数被调用,返回window
-
使用call、apply、bind,传入什么返回什么
-
作为对象方法调用,返回对象本身
-
在class的方法中调用,返回本身
-
在箭头函数中,取上级作用域this的值
2.手写bind函数
// 模拟 bind Function.prototype.bind1 = function () { // 将参数拆解为数组 const args = Array.prototype.slice.call(arguments) // 获取 this(数组第一项) const t = args.shift() // fn1.bind(...) 中的 fn1 const self = this // 返回一个函数 return function () { return self.apply(t, args) } }
// 闭包隐藏数据,只提供 API function createCache() { const data = {} // 闭包中的数据,被隐藏,不被外界访问 return { set: function (key, val) { data[key] = val }, get: function (key) { return data[key] } } } const c = createCache() c.set('a', 100) console.log( c.get('a') )
let a for (let i = 0; i < 10; i++) { a = document.createElement('a') a.innerHTML = i + '<br>' a.addEventListener('click', function (e) { e.preventDefault() alert(i) }) document.body.appendChild(a) }