變數提升的理解
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