慕课网-前端JavaScript面试技巧(双越)-第4章 作用域、闭包
慕课网学习笔记-前端JavaScript面试技巧(双越)- 第4章 JS基础知识(中)- 作用域、闭包
question
题目:
1、说一下对变量提升的理解
2、说明this几种不同的使用场景
3、创建10个 <a>
标签,点击的时候弹出对应的序号
4、如何理解作用域
5、实际开发中闭包的应用
Knowledge-point
知识点:
-
执行上下文
-
this
-
作用域
-
作用域链
-
闭包
执行上下文-Execution-context
执行上下文
-
范围:一段
<script>
或者一个函数 -
全局:变量定义、函数声明 【针对一段
<script>
里面】 -
函数:变量定义、函数声明、this、arguments
PS:注意“函数声明” 和 “函数表达式” 的区别
console.log(a); // undefined
var a = 100;
fn('zhansan'); // zhangsan, 20
function fn(name) {
age = 20;
console.log(name, age);
var age;
}
this
this 要在执行时才能确认值,定义时无法确认
this的使用场景
-
作为构造函数执行
-
作为对象属性执行
-
作为普通函数执行 【this指向window】
-
call、 apply、 bind
var a = {
name: 'A',
fn: function() {
console.log(this.name);
}
}
a.fn(); // A, this === a
a.fn.call({name: 'B'}); // B, this === {name: 'B'}
var fn1 = a.fn;
fn1(); // 空, this === window
作用域-action-scope
作用域
-
全局作用域
-
函数作用域
-
块级作用域(ES6新增)
作用域链
自由变量:一个变量在当前作用域没有定义,但被使用了
var a = 100;
function fn() {
var b = 200;
// 当前作用域没有定义的变量,即“自由变量”
console.log(a);
console.log(b);
}
fn();
var a = 100;
function F1() {
var b = 200;
function F2() {
var c = 300;
console.log(a); // a是自由变量
console.log(b); // b是自由变量
console.log(c);
}
F2();
}
F1();
闭包-closure
闭包的使用场景
-
函数作为返回值
-
函数作为参数传递
函数作为返回值
function F1() {
var a = 100;
// 返回一个函数(函数作为返回值)
return function() {
console.log(a); // 自由变量,去定义它的父作用域寻找
}
}
// f1 得到一个函数
var f1 = F1();
var a = 200;
f1(); // 100
函数作为参数传递
function print(fn) {
let b = 200
fn()
}
let b = 100
function fnb() {
console.log(b)
}
print(fnb) // 100
所有的自由变量【闭包】的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方!!!
Answer
创建10个 <a>
标签,点击的时候弹出对应的序号
for(var i = 0; i < 10; i++) {
a = document.createElement('a');
a.innerHTML = i + 1 + "<br>";
document.body.appendChild(a);
}
window.onload = function() {
var oA = document.getElementsByTagName('a');
for(var i = 0; i < oA.length; i++) {
oA[i].onclick = function(num) {
return function() {
alert(num);
}
}(i);
}
}
Application-of-closure
- 实际开发中闭包的应用
// 闭包隐藏数据,只提供 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'))
// 封装变量,收敛权限。
function isFirstLoad() {
var _list = [];
return function(id) {
if (_list.indexOf(id) >= 0) {
return false;
} else {
_list.push(id);
return true;
}
}
}
var firstLoad = isFirstLoad();
console.log(firstLoad(10)); // true
console.log(firstLoad(10)); // false
console.log(firstLoad(20)); // true