1、數組編程
1.數組是值的有序集合。每一個值叫作一個元素,而每一個元素在數組中有一個位置,以數字表示,稱爲索引。JavaScript數組是無類型的:數組元素能夠是任意類型,而且同一個數組中的不一樣元素也可能有不一樣的類型。數組的元素甚至也多是對象或其餘數組,這容許建立複雜的數據結構,如對象的數組和數組的數組。JavaScript數組的索引是基於零的32位數值:第一個元素的索引爲0,最大可能的索引爲4294967294(232-2),數組最大能容納4294967295個元素。數組
全部的索引都是屬性名,但只有在0~232-2之間的整數屬性名纔是索引。全部的數組都是對象,能夠爲其建立任意名字的屬性。但若是使用的屬性是數組的索引,數組的特殊行爲就是將根據須要更新它們的length屬性值。
注意,可使用負數或非整數來索引數組。這種狀況下,數值轉換爲字符串,字符串做爲屬性名來用。既然名字不是非負整數,它就只能當作常規的對象屬性,而非數組的索引。一樣,若是湊巧使用了是非負整數的字符串,它就當作數組索引,而非對象屬性。當使用的一個浮點數和一個整數相等時狀況也是同樣的:數據結構
a[-1.23] = true; // 這將建立一個名爲"-1.23"的屬性 a["1000"] = 0; // 這是數組的第1001個元素 a[1.000] // 和a[1]相等
a = new Array(5); // 數組沒有元素,可是a.length是5 a = []; // 建立一個空數組,length = 0 a[1000] = 0; // 賦值添加一個元素,可是設置length爲1001
2.數組的實現是通過優化的,用數字索引來訪問數組元素通常來講比訪問常規的對象屬性要快不少。app
var isArray = Function.isArray || function(o){ return typeof o === "object" && Object.prototype.toString.call(o)=== "[object Array]"; };
3.indexOf()和lastIndexOf()方法不接收一個函數做爲其參數。第一個參數是須要搜索的值,第二個參數是可選的:它指定數組中的一個索引,從那裏開始搜索。若是省略該參數,indexOf()從頭開始搜索,而lastIndexOf()從末尾開始搜索。第二個參數也能夠是負數,它表明相對數組末尾的偏移量,對於splice()方法:例如,-1指定數組的最後一個元素。函數
4.reduce()時只有一個參數:沒有指定初始值。當不指定初始值調用reduce()時,它將使用數組的第一個元素做爲其初始值。這意味着第一次調用化簡函數就使用了第一個和第二個數組元素做爲其第一個和第二個參數優化
5.一旦every()和some()確認該返回什麼值它們就會中止遍歷數組元素。some()在斷定函數第一次返回true後就返回true,但若是斷定函數一直返回false,它將會遍歷整個數組。every()剛好相反:它在斷定函數第一次返回false後就返回false,但若是斷定函數一直返回true,它將會遍歷整個數組。注意,根據數學上的慣例,在空數組上調用時,every()返回true,some()返回false。ui
6.Array.sort()方法將數組中的元素排序並返回排序後的數組。當不帶參數調用sort()時,數組元素以字母表順序排序。若是數組包含undefined元素,它們會被排到數組的尾部。爲了按照其餘方式而非字母表順序進行數組排序,必須給sort()方法傳遞一個比較函數。this
7.字符串是不可變值,故當把它們做爲數組看待時,它們是隻讀的。如push()、sort()、reverse()和splice()等數組方法會修改數組,它們在字符串上是無效的。spa
2、函數prototype
1.函數聲明語句的語法以下:
function funcname([arg1[, arg2[..., argn]]]){
statements
}
funcname是要聲明的函數的名稱的標識符。函數名以後的圓括號中是參數列表,參數之間使用逗號分隔。當調用函數時,這些標識符則指代傳入函數的實參。
2.函數聲明語句並不是真正的語句,ECMAScript規範只是容許它們做爲頂級語句。它們能夠出如今全局代碼裏,或者內嵌在其餘函數中,但它們不能出如今循環、條件判斷,或者try/cache/finally以及with語句中。注意,此限制僅適用於以語句聲明形式定義的函數。函數定義表達式能夠出如今JavaScript代碼的任何地方。
3.一個典型的函數定義表達式包含關鍵字function,跟隨其後的是一對圓括號,括號內是一個以逗號分割的列表,列表含有0個或多個標識符(參數名),而後再跟隨一個由花括號包裹的JavaScript代碼段(函數體),例如:
// 這個函數返回傳入參數值的平方 var square = function(x){ return x * x; }
4.用於初始化一個新建立的對象的函數稱爲構造函數。構造函數的命名規則(首字母大寫)和普通函數是如此不一樣還有另一個緣由,構造函數調用和普通函數調用是不盡相同的。構造函數就是用來「構造新對象」的,它必須經過關鍵字new調用,若是將構造函數用作普通函數的話,每每不會正常工做。若是構造函數調用在圓括號內包含一組實參列表,先計算這些實參表達式,而後傳入函數內,這和函數調用和方法調用是一致的。但若是構造函數沒有形參,JavaScript構造函數調用的語法是容許省略實參列表和圓括號的。凡是沒有形參的構造函數調用均可以省略圓括號。
5.若是函數掛載在一個對象上,做爲對象的一個屬性,就稱它爲對象的方法。當經過這個對象來調用函數時,該對象就是這次調用的上下文(context),也就是該函數的this的值。一個方法無非是個保存在一個對象的屬性裏的JavaScript函數。
6.this是一個關鍵字,不是變量,也不是屬性名。JavaScript的語法不容許給this賦值。和變量不一樣,關鍵字this沒有做用域的限制,嵌套的函數不會從調用它的函數中繼承this。若是嵌套函數做爲方法調用,其this的值指向調用它的對象。若是嵌套函數做爲函數調用,其this值不是全局對象(非嚴格模式下)就是undefined(嚴格模式下)。不少人誤覺得調用嵌套函數時this會指向調用外層函數的上下文。若是你想訪問這個外部函數的this值,須要將this的值保存在一個變量裏,這個變量和內部函數都同在一個做用域內。一般使用變量self來保存this。
7.arguments.callee 表明函數名,多用於遞歸調用
8.大多數(非所有)的toString()方法的實現都返回函數的完整源碼。內置函數每每返回一個相似「[native code]」的字符串做爲函數體。
9.不徹底函數編程是一種函數編程技巧,即把一次完整的函數調用拆成屢次函數調用,每次傳入的參數都是完成參數的一部分,每次才分開的函數就叫作不徹底函數。每次函數調用就叫作不徹底調用。
10.
(function(){ // mymodule()函數重寫爲匿名的函數表達式 // 模塊代碼 }()); // 結束函數定義並當即調用它
這種定義匿名函數並當即在單個表達式中調用它的寫法很是常見,已經成爲一種慣用法了。注意上面代碼的圓括號的用法,function以前的左圓括號是必需的,由於若是不寫這個左圓括號,JavaScript解釋器會試圖將關鍵字function解析爲函數聲明語句。使用圓括號JavaScript解釋器纔會正確地將其解析爲函數定義表達式。使用圓括號是習慣用法,儘管有些時候沒有必要也不該當省略。這裏定義的函數會當即調用。
11.每一個JavaScript函數(ECMAScript 5中的Function.bind()方法返回的函數除外)都自動擁有一個prototype屬性。這個屬性的值是一個對象,這個對象包含惟一一個不可枚舉屬性constructor。constructor屬性的值是一個函數對象:
var F = function(){}; // 這是一個函數對象 var p = F.prototype; // 這是F相關聯的原型對象 var c = p.constructor; // 這是與原型相關聯的函數 c === F // => true: 對於任意函數F.prototype.constructor==F
能夠看到構造函數的原型中存在預先定義好的constructor屬性,這意味着對象一般繼承的constructor均指代它們的構造函數。因爲構造函數是類的「公共標識」,所以這個constructor屬性爲對象提供了類。
var o = new F(); //建立類F的一個對象 o.constructor === F // => true,constructor屬性指代這個類
12.構造函數是類的公有標識。在JavaScript中也能夠定義對象的類,讓每一個對象都共享某些屬性,這種「共享」的特性是很是有用的。類的成員或實例都包含一些屬性,用以存放或定義它們的狀態,其中有些屬性定義了它們的行爲(一般稱爲方法)。這些行爲一般是由類定義的,並且爲全部實例所共享。例如,假設有一個名爲Complex的類用來表示複數,同時還定義了一些複數運算。一個Complex實例應當包含複數的實部和虛部(狀態),一樣Complex類還會定義複數的加法和乘法操做(行爲)。在JavaScript中,類的實現是基於其原型繼承機制的。若是兩個實例都從同一個原型對象上繼承了屬性,咱們說它們是同一個類的實例。
13.判斷是不是函數
function isFunction(x){ return Object.prototype.toString.call(x)=== "[object Function]"; }
14.bind
var sum = function(x,y){ return x + y }; //返回兩個實參的和值 // 建立一個相似sum的新函數,但this的值綁定到null // 而且第一個參數綁定到1,這個新的函數指望只傳入一個實參 var succ = sum.bind(null, 1); succ(2)// => 3: x綁定到1,並傳入2做爲實參y function f(y,z){ return this.x + y + z }; //另一個作累加計算的函數 var g = f.bind({x:1}, 2); //綁定this和y g(3) // => 6: this.x綁定到1,y綁定到2,z綁定到3
if(!Function.prototype.bind){ Function.prototype.bind = function(o /*, args */){ // 將this和arguments的值保存至變量中 // 以便在後面嵌套的函數中可使用它們 var self = this, boundArgs = arguments; // bind()方法的返回值是一個函數 return function(){ // 建立一個實參列表,將傳入bind()的第二個及後續的實參都傳入這個函數 var args = [], i; for(i = 1; i < boundArgs.length; i++)args.push(boundArgs[i]); for(i = 0; i < arguments.length; i++)args.push(arguments[i]); // 如今將self做爲o的方法來調用,傳入這些實參 return self.apply(o, args); }; }; }
15.try/catch語句已經可使用多catch從句了,在catch從句的參數中加入關鍵字if以及一個條件判斷表達式:
try { // 這裏可能會拋出多種類型的異常 throw 1; } catch(e if e instanceof ReferenceError){ // 這裏處理引用錯誤 } catch(e if e === "quit"){ // 這裏處理拋出的字符串是"quit"的狀況 } catch(e if typeof e === "string"){ // 處理其餘字符串的狀況 } catch(e){ // 處理餘下的異常狀況 } finally { // finally從句正常執行 }
16.若是函數只計算一個表達式並返回它的值,關鍵字return和花括號均可以省略
let succ=function(x)x+1, yes=function()true, no=function()false;
17.內聯命名函數
var func1 = function func2(){ console.log(func1 === func2) } func1() // true func2() // Uncaught ReferenceError: func2 is not defined
儘管能夠給內聯函數進行命名,但這些名稱只能在自身函數內部可見。內聯函數的名稱和變量名稱有點像,它們的做用域僅限於聲明它們的函數。