电竞比分网-中国电竞赛事及体育赛事平台

分享

JavaScript必知必會+理解總結(jié)

 橙zc 2014-06-22

英文原文:What should every JavaScript programmer know? 編譯:西城一隅

這是stackoverflow上的一個老問題,卻有個干貨答案,但是擴(kuò)展的信息量很大,我只在此拋個磚。

Not jQuery. Not YUI. Not 等等…

js的框架的確很有用,但是它們卻常常把一些js的丑陋細(xì)節(jié)和DOM原理給你隱藏了。如果你的目標(biāo)是做一個精通javascript的工程師,那花大把的時間放在框架上可能恰恰背道而馳了。

下面就有javascript這門語言的一些特性,你應(yīng)該知道并且深諳此道,但是很多人可能還并不清楚。

一、對象屬性,object.prop和object['prop']是一回事(所以你能停止使用eval了嗎?!3KU);對象的屬性多是String類型(有些也是數(shù)組Array)

for…in是什么情況下使用,什么情況慎用?

方括號可以通過變量來訪問屬性

1
2
3
4
person.name;
person['name'];
var propertyName = 'name';
person[propertyName]; // name

當(dāng)屬性是帶空格的string時就只能用方括號了:person['first name'];

for…in 循環(huán)輸出的屬性名順序不可預(yù)測,使用之前先檢測對象是否為null 或者 undefined

二、屬性檢測;undefined和null;為什么鮮為人知的in運(yùn)算符非常有用,以及它和typeof、undefined的區(qū)別;hasOwnProperty;delete作用

undefined好理解一般用來表示未定義,而且不能用delete來刪除它。

null 表示一個空對象指針 所以 typeof null返回 object

undefined派生自null alert(null == undefined) 返回true; 但alert(null === undefined)就返回false了

關(guān)于hasOwnProperty和Object:

hasOwnProperty是js中唯一一個處理屬性但是不查找原型鏈的函數(shù)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Object.prototype.prop = 'propsss';
var obj = {und:undefined};
obj.prop; // propsss
'und' in obj; // true
obj.hasOwnProperty('prop'); // false
obj.hasOwnProperty('und'); // true
//只有hasOwnProperty可以給出正確和期望的結(jié)果,尤其在遍歷一個對象時
//除了hasOwnProperty外,沒有其他方法可以排除原型鏈上的屬性(不是定義在對象自身上的屬性)
//如果hasOwnProperty被占用呢?來看:
var obj = {
    hasOwnProperty: function(){
        return false;
    },
    prop: 'this is bad...'
};
obj.hasOwnProperty('prop'); // 總是返回false
//這樣解決:
{}.hasOwnProperty.call(obj,'prop'); // 返回true

var o =new Object();

Object的每個實(shí)例都具有下列屬性方法:

1.Constructor:保存著用于創(chuàng)建當(dāng)前對象的函數(shù) 上面例子 構(gòu)造函數(shù)就是 Object()

2.hasOwnProperty(prop):檢查給定的屬性是否在當(dāng)前對象實(shí)例中(而不是在實(shí)例的原型中)。作為參數(shù)的屬性必須以string形式指定

3.isPrototypeOf(object):用于檢查傳入的對象是否是另一個對象的原型。

4.propertyIsEnumerable(propertyName):用于檢查給定的屬性是否能夠使用for in語句

5.toLocaleString():返回對象的字符串表示,與環(huán)境的地區(qū)對應(yīng)

6.toString():同上

7.valueOf(): 返回對象的字符串、number、Boolean表示。通常與toString()相同

三、Number類型就是浮點(diǎn)類型(64位浮點(diǎn)數(shù));使用浮點(diǎn)數(shù)會遇到語言無關(guān)性的問題;避免使用parseInt時的八進(jìn)制陷阱

ECMAScript5不具有解析八進(jìn)制的能力,可在IE7和chrome上測試 parseInt(069);

ES3和ES5之間存在分歧

javascript中的乘法問題:

一般可以用 10000 作為基數(shù)

31.12 * 10000 * 9.7 / 10000

四、嵌套函數(shù)作用域;避免全局變量導(dǎo)致的意外而使用var的必要性;閉包的作用域如何結(jié)合使用;在循環(huán)與閉包的問題

作用域和var關(guān)鍵字的面試題

1
2
3
4
5
function(){
var a=b=10;
}
console.log(a);
console.log(b);

循環(huán)中使用閉包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function createFunctions(){
    var result = new Array();
    for(var i=0;i<10;i++){
        result[i] = fucntion(){
            return i;
        }
    }
    return result;
}
//每個函數(shù)的作用域鏈中都保存著createFunctions()函數(shù)的活動對象,所以他們引用的都是同一個變量i。
//當(dāng)createFunctions()返回后 變量i的值是10
//所以可以這樣寫
for(var i=0;i<10;i++){ 
  result[i] = function(num){
    return function(){ 
        return num; 
    }; 
  }(i); 
}

之前寫過的閉包的理解關(guān)于閉包

五、全局變量和window對象的屬性產(chǎn)生沖突怎么辦(它們其實(shí)是一回事);全局變量和DOM元素在IE中的沖突;在全局作用域中使用var來避免這些問題

六、 function語句在解析時會被提升(不管function被放置在哪里,它都會被移動到定義時所在作用域的頂層) 函數(shù)聲明和函數(shù)表達(dá)式;為什么命名函數(shù)表達(dá)式不應(yīng)該使用

關(guān)于函數(shù)聲明提升

解析器會執(zhí)行一個函數(shù)聲明提升(function decalaration hoisting)的過程,讀取并將函數(shù)聲明添加到執(zhí)行環(huán)境中。

對代碼求值時js引擎在第一遍會聲明函數(shù)并將它們放到源代碼樹的頂部。

1
2
3
4
5
6
7
8
9
alert(sum(10,10))
function sum(n1,n2){
    return n1+n2;
}
//單獨(dú)使用下面代碼時,函數(shù)表達(dá)式會出錯:
alert(sum(10,10));
var sum = function (n1,n2){
    return n1+n2;
}

關(guān)于命名函數(shù)表達(dá)式

1、命名函數(shù)表達(dá)式即被認(rèn)為是函數(shù)聲明也被認(rèn)為是函數(shù)表達(dá)式

1
2
3
4
typeof g; // "function"
var f = function g(){};
//上面這個例子論證了 jScript 是如何把一個命名函數(shù)表達(dá)式處理成一個函數(shù)聲明的
//在函數(shù)聲明發(fā)生之前就把 g 給解析了   【在IE中檢測】

2、命名函數(shù)表達(dá)式還能創(chuàng)建兩個不同的函數(shù)對象—-這是js的bug

1
2
3
4
5
var f = function g(){};
f === g;  //false
f.prop = 'a prop';
g.prop; // undefined  【在IE中檢測】

竟然創(chuàng)建了兩個對象,他們之間還不是引用的關(guān)系,是不是很有趣。。。我只能說:呵呵 interesting……

3、在條件語句中命名函數(shù)表達(dá)的聲明式仍然會被解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var f = function g(){
    return 1;
};
if(false){
    f= function g(){
        return 100;
    };
}
g(); //猜猜返回什么 【在IE中檢測】
//還有arguments也中槍了
var f = function g(){
    return [
      arguments.callee == f,
      arguments.callee == g
    ];
  };
console.log(f()); // [true, false]
console.log(g()); // [false, true]   【在IE中檢測】

注:上面的3條準(zhǔn)確的說應(yīng)該是算是jScript的bug

七、構(gòu)造函數(shù);prototype屬性;new運(yùn)算符的運(yùn)行機(jī)制;利用這些方法實(shí)現(xiàn)一個類-子類-實(shí)例的系統(tǒng);在何時應(yīng)該考慮使基于閉包的對象來替代原型設(shè)計(jì)

八、this是在函數(shù)調(diào)用時才被確定的而不是定義的時候;把函數(shù)當(dāng)做參數(shù)傳入時不像其他語言那樣執(zhí)行;如何使用閉包或者Function.prototype.bind來解決這些問題呢

關(guān)于this的調(diào)用,直接上代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var Dog = {
    toString: function() { return 'dog';},
    fn: function() { alert(this);},
};
var Cat = {
    toString: function() { return 'cat';}
};
Dog.fn(); // dog
Dog['fn']() // dog
Cat.fn = Dog.fn;
Cat.fn(); // cat
var func = Dog.fn;
func(); // window

上面代碼很簡單 請自行補(bǔ)腦……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Obj.method = function() {
    var self = this;
    function test() {
        //this 被設(shè)置為全局對象(window)
        //self 指向 Obj 對象
    }
}
//想到了arguments做個低耦合的遞歸求階乘
function factorial(num) {
    if(num<=1)
        return 1;
    else
        return num*arguments.callee(num-1);
}
//callee指向擁有這個arguments對象的函數(shù)

之前寫過的關(guān)于this的理解

關(guān)于Function.prototype.bind(thisArg [, arg1 [, arg2, …]]):

這是ECMAScript 5中的方法看看Opera的對它的介紹吧

簡單翻譯就是:

Function.prototype.bind 返回一個新的函數(shù)對象,該對象的 this 綁定到了thisArg參數(shù)上。本質(zhì)就是:這允許你在其他對象鏈中執(zhí)行一個函數(shù)

但是很多瀏覽器不支持,通過一個js的hack看看原理吧:

1
2
3
4
5
6
7
8
9
10
11
12
if(!Object.bind){
    Function.prototype.bind = function(owner){
        var self = this;
        var args = Array.prototype.slice.call(arguments,1);
        return function() {
            return self.allpy(
                args.length===0 ? arguments : arguments.length===0? args:
                    args.contact(Array.prototype.slice.call(arguments,0))
            );
        };
    };
}

九、其他的ES5新特性如indexOf  、 forEach 以及Array使用函數(shù)式編程;舊瀏覽器如何兼容這些新的方法;使用匿名函數(shù)調(diào)用這些方法來使代碼更加緊致具有可讀性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Array.prototype.indexOf(searchString ,position)
    var data = [1,3,5,7,9];
    console.log(data.indexOf(5)); //2
    console.log(data.indexOf(5,4)); //-1  從4號位開始搜索
    console.log(data.indexOf('7'));  //-1  7!== '7'
Array.prototype.lastIndexOf //從末尾開始查找
Array.prototype.some //某些條件符合
    var arr = [1,2,3,4,11];
    function larger(item){
        return item> 10   
    }
    console.log(arr.some(larger)?'ok':'no...');
    //注:只要有一條符合 即返回true 不再執(zhí)行
Array.prototype.every // all符合  和some相比就是返回的 true 和 false 調(diào)換一下
Array.prototype.forEach //類似jQ里的each
    [1, 2 ,3, 4].forEach(alert);
    [1, 2 ,3, 4].forEach(console.log);//FF下運(yùn)行 不知為什么chrome不行。。。。。
Array.prototype.map //映射 類似forEach 把原數(shù)組映射成新數(shù)組
    var arr = [1,3,5,7];
    var result = arr.map(function(item){
        return item * item;
    });
    console.log(result); //求各項(xiàng)平方
Array.prototype.filter //篩選
    var filter = [0,2,3,0,undefined].filter(function(item){
        return item;
    });
    console.log(filter);
    //filter的callback函數(shù)需要返回值為 true 或 false。若為false則過濾掉
Array.prototype.reduce //不是減少  是一種迭代
    var sum = [1,2,3,4,5].reduce(function(pre,current,index,array) {
        return pre + current;
    });
console.log(sum); //15
Array.prototype.reduceRight //right 自然是從數(shù)組末未開始

這些都是 ES5 中 Array 對象的擴(kuò)展方法

PS:還是點(diǎn)此自行補(bǔ)腦,我也在研究中…..后續(xù)會再補(bǔ)充

十、瀏覽器和js代碼之間控制流程的原理;同步和異步執(zhí)行;事件在運(yùn)行時觸發(fā)和事件在控制返回時觸發(fā)的區(qū)別;調(diào)用同步執(zhí)行的方法如alert而引起控制流重新進(jìn)入的潛在問題(翻譯不通,請自行補(bǔ)腦)。

十一、跨window腳本對instanceof的影響 在不同的DOM中跨window腳本對控制流的影響;postMessage怎么解決這個問題

postMessage就是HTML5解決跨域問題引入的API,使得多個iframe/window實(shí)現(xiàn)跨域通信。

寫了個postMessage跨域通信的demo: 點(diǎn)此查看

最重要的是,你需要批判的去看待javascript,承認(rèn)因?yàn)榉N種歷史原因而導(dǎo)致各種不完美(甚至比其他語言還要糟糕),并要避免各種陷阱。Crockford在這方面的研究很值得學(xué)習(xí)(雖然我不完全認(rèn)同他的《javascript語言精粹》)


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多