練習(xí)
下面的代碼輸出多少娩嚼?修改代碼讓 fnArr[i]()
輸出 i
旬痹。使用 兩種以上的方法
var fnArr = [];
for (var i = 0; i < 10; i++) {
fnArr[i] = function(){
return i;
};
}
console.log(fnArr[3]()); // => 10
/*
產(chǎn)生的原因是,
變量 i 和匿名函數(shù) function(){return i;}
構(gòu)成的閉包在 console.log(fnArr[3]()) 執(zhí)行 fnArr[3]() 時瞧挤,
所引用的變量 i 的值為10
*/
解決方法如下
// 方法一
var fnArr = [];
for (var i = 0; i < 10; i++) {
(function(i){
fnArr[i] = function(){
return i;
};
})(i);
}
console.log(fnArr[3]()); // => 3
// 方法二
var fnArr = [];
for (var i = 0; i < 10; i++) {
fnArr[i] = (function(i){
return function(){
return i;
};
})(i);
}
console.log(fnArr[3]()); // => 3
// 方法三
var fnArr = [];
for (let i = 0; i < 10; i++) {
fnArr[i] = function(){
return i;
};
}
console.log(fnArr[3]()); // => 3
封裝一個汽車對象钧忽,可以通過如下方式獲取汽車狀態(tài)
var Car = (function(){
var speed = 0;
function setSpeed(s){
speed = s;
}
/* your code */
function getSpeed(){
return speed;
}
function accelerate(){
speed += 10;
}
function decelerate(){
speed >= 10 ? speed -= 10 : console.log(`減速幅度超過最低速度眷蜓,請修正`);
}
function getStatus(){
return speed > 0 ? `running` : `stop`;
}
/* your code */
return {
setSpeed: setSpeed,
/* code */
getSpeed: getSpeed,
accelerate: accelerate,
decelerate: decelerate,
getStatus: getStatus
};
})();
// 測試
Car.setSpeed(30);
Car.getSpeed(); // => 30
Car.accelerate();
Car.getSpeed(); // => 40;
Car.decelerate();
Car.decelerate();
Car.getSpeed(); // => 20
Car.getStatus(); // => 'running';
Car.decelerate();
Car.decelerate();
Car.getStatus(); // => 'stop';
下面這段代碼輸出結(jié)果是质帅?為什么朴肺?
var a = 1;
setTimeout(function(){
a = 2;
console.log("1: " + a);
}, 0);
var a;
console.log("2: " + a);
a = 3;
console.log("3: " + a);
// 運(yùn)行結(jié)果如下
// 2: 1
// 3: 3
// <· undefined -->匿名函數(shù)默認(rèn)返回的炕檩,忽略
// 1: 2
// 分析如下:
// 先將聲明的變量提升斗蒋,得到
var a;
var a;
a = 1;
setTimeout(function(){
a = 2;
console.log("1: " + a);
}, 0);
console.log("2: " + a);
a = 3;
console.log("3: " + a);
因為定時器的運(yùn)行機(jī)制是,將指定的代碼移出本次執(zhí)行笛质,等到下一輪 Event Loop 時泉沾,再檢查是否到了指定時間。如果到了妇押,就執(zhí)行對應(yīng)的代碼跷究;如果不到,就等到再下一輪 Event Loop 時重新判斷敲霍。這意味著俊马,setTimeout 指定的代碼,必須等到本次執(zhí)行的所有代碼都執(zhí)行完肩杈,才會執(zhí)行柴我。
// 所以,執(zhí)行順序為
// 1
console.log("2: " + a); // => 2: 1
// 2
a = 3;
console.log("3: " + a); // => 3: 3
// 3
a = 2;
console.log("1: " + a); // => 1: 2
下面這段代碼輸出結(jié)果是扩然?為什么艘儒?
var flag = true;
setTimeout(function(){
flag = false;
}, 0);
while(flag) {}
console.log(flag);
// tips: 千萬不要把這段代碼放到控制臺里運(yùn)行,后果自負(fù)
依據(jù) setTimeout 的運(yùn)行機(jī)制与学,以上代碼執(zhí)行順序如下
var flag = true;
while(flag) {}
console.log(flag);
flag = false;
/*
因為 flag = true彤悔,while(flag){} 是個死循環(huán),
瀏覽器不會執(zhí)行 console.log(flag)索守,更不會執(zhí)行 flag = false
*/
下面這段代碼輸出晕窑?如何輸出 delayer:0, delayer:1...
(使用閉包來實現(xiàn))
for (var i = 0; i < 5; i++) {
setTimeout(function(){
console.log('delayer:' + i);
}, 0);
console.log(i);
}
運(yùn)行結(jié)果如下
// 0
// 1
// 2
// 3
// 4
// <· undefined --> 匿名函數(shù)默認(rèn)返回的,忽略
// delayer:5
// delayer:5
// delayer:5
// delayer:5
// delayer:5
根據(jù)變量提升的規(guī)則卵佛,以及定時器的運(yùn)行機(jī)制,以上代碼整理如下
var i;
for (i = 0; i < 5; i++) {
console.log(i);
setTimeout(function(){
console.log('delayer:' + i);
}, 0);
}
// console.log(i) 的打印結(jié)果自不必說,當(dāng)代碼執(zhí)行到 setTimeout 時,在下一輪事件循環(huán)中的匿名函數(shù)要打印5次 i ,其值已自增到5
改造如下
for (var i = 0; i < 5; i++) {
(function(i){
setTimeout(function(){
console.log('delayer:' + i);
}, 0);
})(i);
console.log(i);
}
結(jié)果如下
如何獲取元素的真實寬高
var p = document.createElement("p");
var body = document.querySelector("body");
body.append(p);
var mp = document.querySelector("p");
// console.log(window.getComputedStyle(p, null))
// console.log(p.style)
function getStyle(element){ // 兼容低版本IE
return element.currentStyle ? element.currentStyle : window.getComputedStyle(element, null);
}
console.log(getStyle(mp).height); // 0px
console.log(getStyle(mp).width); // 1264px
URL 如何編碼解碼低滩?為什么要編碼恕沫?
-
編碼方法:
- encodeURI()
- encodeURIComponent()
-
解碼方法:
- decodeURI()
- decodeURIComponent()
其中,
encodeURI
與encodeURIComponent
區(qū)別不編碼字符 范圍 encodeURI
1. ASCII字母
2. 數(shù)字
3.~!@#$&*()=:/,;?+'
編碼范圍小于 encodeURIComponent
encodeURIComponent
1. ASCII字母
2. 數(shù)字
3.~!*()'
- 編碼原因:
對 URL 來說腾它,之所以要進(jìn)行編碼,是因為 URI 中有些字符會引起歧義虏两,例如鍵值對的值中字符串包含=
或&
URL編碼的原則就是使用安全的字符(沒有特殊用途或者特殊意義的可打印字符)去表示那些不安全的字符另外旁瘫,你還清楚
URI
與URL
分別是什么嗎惠况?
URI 是統(tǒng)一資源標(biāo)識符,而 URL 是統(tǒng)一資源定位符赐俗。因此秩彤,籠統(tǒng)地說漫雷,每個 URL 都是 URI谤辜,但不一定每個 URI 都是 URL
補(bǔ)全如下函數(shù)丑念,判斷用戶的瀏覽器類型
function isAndroid(){
return navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Adr') > -1
}
function isIphone(){
return navigator.userAgent.indexOf('iPhone') > -1
}
function isIpad(){
return navigator.userAgent.indexOf('iPad') > -1
}
function isIOS(){
return !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
}
小結(jié)
-
函數(shù)都是“自私”的涡戳,除非通過
return
關(guān)鍵字,否則外界無法訪問到函數(shù)的變量脯倚,而且就算return
關(guān)鍵字將變量返回渔彰,外界也只能是“可遠(yuǎn)觀而不可褻玩焉”(變量是朕的,朕不給推正,你不能搶恍涂;就算朕給你看,你也不能胡來植榕,要聽朕的話@_@)
正是由于函數(shù)的這一特性再沧,ES5 才能通過函數(shù)來實現(xiàn)塊級作用域,
if () {}
内贮、for () {}
产园,如果為了美觀汞斧,大可用{}
將編寫的代碼包裹起來,但要記住什燕,這些花括號{}
在 ES5 中都不會形成塊級作用域粘勒,函數(shù)的花括號{}
形成的函數(shù)作用域才是“封閉”的ES6 中 單純使用
{}
會形成塊級作用域