JS中常見的幾個問題及概念

《我心中尚未崩壞的地方》

寫在前面

此文作為筆記所用,且有的地方可能有點小錯誤什么的,歡迎大佬們指點或指正,小花在此謝過~

1. JS中淺拷貝及深拷貝

數組淺拷貝代碼舉例

var arr = ["One","Two","Three"];

var arrto = arr;
arrto[1] = "test";
document.wrirteln("數值的原始值:" + arr + "<br />");  //Export:數組的原始值:One,test,Three

document.wrirteln("數值的原始值:" + arrto + "<br />");  //Export:數組的新值:One,test,Three
  • 解決數組淺拷貝的方法有:

    1. arr.slice(0) 得到的是一個新數組
    2. var arrtooo = arr.concat();
  • 對象的深拷貝(將對象中屬性遍歷一次得到一個新數組):

方法一:

var deepCopy = function(source){
    var result = {};
    
    for (var key in source){
        result[key] = typeof source[key] === 'object'?deepCopy(source[key]):source[key];
    }
    
    return result;
}

方法二:

str = JSON.stringify(obj), //系列化對象
newobj = JSON.parse(str); //還原

將它封裝成一個函數之后:
function jsonClone(obj) {
    return JSON.parse(JSON.stringify(obj));
}

var clone = jsonClone(obj);

2. 關于chrome無法訪問XMLHttpRequest

關于chrome無法訪問XMLHttpRequest,原因是chrome 到安全性的問題,限制了本地跨域,可用的方式有,利用jQuery來改寫,還有就是在chrome圖標屬性的目標項更改參數設置為"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" (此處有一個空格)--args --disable-web-security

3. JSON的輸出方式

//此部分不重要,初學者可觀看
var data01 = {
        "total_page": 2,
        "cover_url_large": "xxx",
        "tracks": [{
            "id": 237730,
            "track_title": "張杰 - 無情的情書(live版)",
            "announcer": {
                "nickname": "tiny121",
            },
            "duration": 310,
            "subordinated_album": {
                "album_title": "tiny550_album 001",
            },
            "source": 2,
        },
            {
                "track_title": "張杰 - 無情的情書(...)",
                "announcer": {
                    "nickname": "dgfsgdfdhfgdsgfhdsgu",
                },
                "duration": 310,
                "subordinated_album": {
                    "id": 86492,
                },
                "source": 2,
            }
        ]
    }
    document.write(data01.tracks[0].track_title);
    document.write(data01.tracks[0].announcer.nickname);
    document.write(data01.tracks[1].announcer.nickname);
    document.write(data01.tracks[1].track_title);
    
    //其中data01為json名,tracks為一個數組包含多個對象

4. 自執行匿名函數(IIFE)

  • 常見格式:(function() { /* code */ })();
  • 解釋:包圍函數(function(){})的第一對括號向腳本返回未命名的函數,隨后一對空括號立即執行返回的未命名函數,括號內為匿名函數的參數。
  • 作用:可以用它創建命名空間,只要把自己所有的代碼都寫在這個特殊的函數包裝內,那么外部就不能訪問,除非你允許(變量前加上window,這樣該函數或變量就成為全局)。各JavaScript庫的代碼也基本是這種組織形式。
  • 最大的用途是創建閉包

注意:函數聲明后面不允許在后面直接使用小括號

函數聲明和函數表達式不同之處在于,一、Javascript引擎在解析javascript代碼時會‘函數聲明提升’(Function declaration Hoisting)當前執行環境(作用域)上的函數聲明,而函數表達式必須等到Javascirtp引擎執行到它所在行時,才會從上而下一行一行地解析函 數表達式,二、函數表達式后面可以加括號立即調用該函數,函數聲明不可以,只能以fnName()形式調用 。

fnName();

function fnName(){
    ...
} //正常,因為‘提升’了函數說明,函數調用可在函數聲明之前

fnName();
var fnName = function(){
    ...
}//報錯,變量fnName還未保存對函數的應用,函數調用必須在函數表達式之后

var fnName = function(){
    alert('Hello World');
}(); //函數表達式后面加括號,當JavaScript引擎解析到此處時能立即調用函數

function fnName(){
    alert('Hello World');
}(); //不會報錯,但是JavaScript引擎只解析函數聲明,忽略后面的括號,函數聲明不會被調用

function(){
    console.log('Hello World');
}(); //語法錯誤,雖然匿名函數屬于函數表達式,但是未進行賦值操作,
//所以JavaScript引擎開頭的function關鍵字當做函數聲明,報錯:需要一個函數名

javascript中沒用私有作用域的概念,如果在多人開發的項目上,你在全局或局部作用域中聲明了一些變量,可能會被其他人不小心用同名的變量給覆蓋 掉,根據javascript函數作用域鏈的特性,可以使用這種技術可以模仿一個私有作用域,用匿名函數作為一個“容器”,“容器”內部可以訪問外部的變 量,而外部環境不能訪問“容器”內部的變量,所以( function(){…} )()內部定義的變量不會和外部的變量發生沖突,俗稱“匿名包裹器”或“命名空間”。

5.dataset 自定義屬性

  • 這里的data-前綴就被稱為data屬性,其可以通過腳本進行定義,也可以應用CSS屬性選擇器進行樣式設置。數量不受限制,在控制和渲染數據的時候提供了非常強大的控制。
var expenseday2 = document.getElementById('day2-meal-expense');  
var typeOfDrink = expenseday2.dataset.drink;
  • 刪除data屬性:delete expenseday2.dataset.meal;
  • 添加data屬性:expenseday2.dataset.dessert = 'icecream';
  • data在css中的使用: .mm[data-name='張含韻']{ }

6. 迭代器模式

提供一種方法順序一個聚合對象中各個元素,而又不暴露該對象內部表示。

  • 訪問一個聚合對象的內容而無需暴露它的內部表示。
  • 訪問一個聚合對象的內容而無需暴露它的內部表示。
  • 遍歷的同時更改迭代器所在的集合結構可能會導致問題

7. map()和filter()

  • filter是滿足條件的留下,是對原數組的過濾;filter 是根據返回的值是否為真來判斷是否保留元素
  • map則是對原數組的加工,映射成一一映射的新數組
function pp(x){return x % 2;}
function px(x){return x % 2;}
var m = xx.map(pp);
var f = xx.filter(px);
  • array.map(callback[, thisObject]);

callback : 從當前的元素函數產生新的數組的元素。
thisObject : 對象作為該執行回調時使用

8. 閉包

閉包是一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。

  • 由于閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。(解決方法是,在退出函數之前,將不使用的局部變量全部刪除)
  • 閉包會在父函數外部,改變父函數內部變量的值。

9. ES5中的bind()方法

bind和call以及apply一樣,都是可以改變上下文的this指向的。不同的是,call和apply一樣,直接引用在方法上,而bind綁定this后返回一個方法,但內部核心還是apply。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容