寫在前面
此文作為筆記所用,且有的地方可能有點小錯誤什么的,歡迎大佬們指點或指正,小花在此謝過~
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
-
解決數組淺拷貝的方法有:
- arr.slice(0) 得到的是一個新數組
- 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。