变量提升的理解
js 语言的执行规则:先定义,后执行变量定义、函数声明就属于定义代码的范畴(注意“函数声明”和“函数表达式”的区别)
说明 this 几种不同的使用场景
this 要在执行时才能确认值,定义时无法确认
var a = {
name: ‘A’,
fn: function () {
console.log(this.name);
}
};
a.fn(); // this === a
a.fn.call({name: ‘B’}); // this === {name: ‘B’}
var fn1 = a.fn;
fn1(); // this === window
全局环境下的 this
function fn() {
console.log(this); // this === window
}
fn();
对象方法中的 this
var obj = {
name: ‘A’,
printName: function () {
console.log(this.name); // this === obj
}
};
obj.printName();
构造函数中的 this
function Foo(name) {
this.name = name; // this === f
}
var f = new Foo(‘can’);
事件函数中的 this
document.getElementById(‘div1’).onclick = function () {
console.log(this); // this === <div id=”div1″>div1</div> 触发当前事件的 Element 对象
};
call apply bind 中的 this
function fn1(name, age) {
console.log(name, age);
console.log(this); // this === {x:100}
}
fn1.call({x: 100}, ‘can’, 22);
fn1.apply({x: 100}, [‘can’, 22]);
var fn2 = function (name, age) {
console.log(name, age);
console.log(this); // this === {y:200}
}.bind({y: 200});
fn2(‘can’, 22);
创建 10 个 a 标签,点击的时候弹出来对应的序号
for (var i = 0; i < 10; i++) {
(function (i) {
// 函数作用域
var a = document.createElement(‘a’);
a.innerHTML = i + ‘<br>’;
a.addEventListener(‘click’, function (e) {
e.preventDefault();
alert(i); // i 是自由变量,去父作用域寻找
});
document.body.appendChild(a);
})(i);
}
作用域
ES5 中,无块级作用域
if (true) {
var name = ‘can’;
}
console.log(name); // ‘can’
函数和全局作用域
var b = 1;
function fn3() {
var b = 2;
console.log(‘fn’, b); // 2
}
console.log(‘global’, b); // 1
fn3();
自由变量
var a = 100;
function fn4() {
var b = 200;
// 当前作用域没有定义的变量,即“自由变量”
console.log(a); // 100 a 是自由变量,去父作用域寻找
console.log(b); // 200
}
fn4();
一个函数的父级作用域,是它定义时的父级作用域,而不是执行时
作用域链,即自由变量的查找
var a = 100;
function fn5() {
var b = 200;
function fn6() {
var c = 300;
console.log(a); // 100 a 是自由变量,去父作用域寻找
console.log(b); // 200 b 是自由变量,去父作用域寻找
console.log(c); // 300
}
fn6();
}
fn5();
闭包的使用场景
1. 函数作为返回值
function fn1() {
var a = 100;
// 返回一个函数(函数作为返回值)
return function () {
console.log(a); // a 是自由变量,去父作用域寻找
}
}
// f1 得到一个函数
var f1 = fn1();
var a = 200;
f1(); // 100
2. 函数作为参数传递
function fn1() {
var a = 100;
// 返回一个函数(函数作为返回值)
return function () {
console.log(a); // a 是自由变量,去父作用域寻找
}
}
// f1 得到一个函数
var f1 = fn1();
function fn2(fn) {
var a = 200;
fn();
}
fn2(f1); // 100
实际开发中闭包的应用
闭包实际应用中主要用于封装变量,收敛权限
function isFirstLoad() {
var list = [];
return function (id) {
if (list.indexOf(id) > -1) {
return false;
} else {
list.push(id);
return true;
}
}
}
// 在 isFirstLoad 函数外面,不可能修改到 list 的值
var firstLoad = isFirstLoad();
firstLoad(10); // true
firstLoad(10); // false
firstLoad(20); // true