Ecmascript262-3 1999年,ie5.5及之後徹底支持,ff,chrome等所有支持
Ecmascript262-4 由於跨越太大,廢棄
Ecmascript262-3.1 後更名ecmascript5 主流瀏覽器支持,ie8部分支持,ie9所有支持chrome
1.1 Array.isArray(arg)
若是是數組,放回true數組
if (!Array.isArray) {
Array.prototype.isArray = function(ar) {
return Object.prototype.toString.call(ar) === 「[object Array]」
}
}瀏覽器
1.2 Object.keys(obj)
把obj的全部屬性枚舉放到數組裏返回,順序取決於for in的順序,Object.keys不枚舉原型鏈中的屬性緩存
if (!Object.keys) {
Object.prototype.keys = function(obj) {
var ar = [];
for (var i in obj) {
if (Object.prototype.hasOwnProperty.call(obj,i) {
ar.push(i);
}
}
return ar;
}
}安全
1.3 FuncProto.bind
fun.bind(thisArg[, arg1[, arg2[, ...]]])
if (!Function.bind) {
Function.prototype.bind = function(context) {
var fn = this,
arg = [];
for (var i = 1, len = arguments.length; i < len; i++) {
arg[i-1] = arguments[i];
}
return function() {
for (var j = 0, len2 = arguments.length; j < len2; j++) {
arg[i++] = arguments[j];
}
fn.apply(context, arg);
}
}
}閉包
1.4 Object.create
Object.create(prototype, [ propertiesObject ])
建立一個對象並返回,讓該對象的prototype對象指向參數的對象app
if (!Object.prototype.create) {
Object.prototype.create = (function() {
function fn() {dom
};
var hasown = Object.prototype.hasOwnProperty;
return function(proto, args) {
var obj;
fn.prototype = proto;
obj = new fn();
fn.prototype = null;
if (args) {
for (var i in args) {
if (hasown.call(args, i)) {
obj[i] = args[i];
}
}
}
return obj;ecmascript
}
}())
}函數
關鍵點是安全:
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
若是參數obj是經過構造函數_new出來的對象,那麼直接返回
若是this不是_的對象,說明可能不是經過new _的調用,因此執行
return new _(obj);
最終執行this._wrapped = obj;
當new ConstructorFn(...) 執行時:
1.一個新對象被建立。它繼承自ConstructorFn.prototype(newobj.prototype=foo.prototype).
2.構造函數 ConstructorFn 被執行。執行的時候,相應的傳參會被傳入,同時上下文(this)會被指定爲這個新實例。new ConstructorFn 等同於 new ConstructorFn(), 只能用在不傳遞任何參數的狀況。
3.若是構造函數返回了一個「對象」,那麼這個對象會取代整個new出來的結果。若是構造函數沒有返回對象,那麼new出來的結果爲步驟1建立的對象,ps:通常狀況下構造函數不返回任何值,不過用戶若是想覆蓋這個返回值,能夠本身選擇返回一個普通對象來覆蓋。固然,返回數組也會覆蓋,由於數組也是對象。
首先判斷參數是否爲對象或函數,若是不是,返回空對象。
而後判斷是否存在原生create,若是有,調用。
若是沒有,經過ctor函數,讓ctort.prototype = prototype;
var result = new ctor();
ctor.prototype = null;
var baseCreate = function(prototype) {
if (!_.isObject(prototype)) return {};
if (nativeCreate) return nativeCreate(prototype);
Ctor.prototype = prototype;
var result = new Ctor;
Ctor.prototype = null;
return result;
};
var property = function(key) {
return function(obj) {
return obj == null ? void 0 : obj[key];
};
};
生成安全的取對象屬性的方法,防止undefined或null取屬性值而報錯。
關鍵點:
obj == null ? void 0 : obj[key];
obj == null 其實是一個隱式轉換,就是當obj是null或undefined的時候。
==的隱式轉換規則,詳見Ecmascript: http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.1
若是雙方類型一致,對比值:
若是是undefined, true
若是是null, true
若是是number,
若是其中一個是NaN,不相等
若是值相等,相等
+0, -0, 0是相等的。
若是是String,
當兩個字符串長度一致,並且對應位置字符一致那麼相等。
若是是Boolean
當二者都是true或者false時候相等。
若是是Object
當二者的指針指向一個對象時相等。
若是類型不一致,
null, undefined相等
string,boolean和number比較時候會轉換成數字再比較
boolean和其餘的比較會轉換成number,true1 false 0
Object和string或number比較會先調用toString或valueOf,獲得值後在比較。
用於優化回調函數:
1) 綁定上下文context,若是有context,返回綁定context的函數,用於後續操做。若是沒有context,直接返回
2)經過客戶端傳入的argCount決定返回函數的參數個數,防止使用arguments對象,由於在一些舊的v8版本中,使用
arguments會致使函數得不到瀏覽器優化。
在函數內部建立一個閉包的迭代函數,而後返回一個函數,判斷參數,初始化而後調用這個迭代函數。
閉包大體有這麼幾個做用:避免命名衝突;私有化變量;變量持久化,讓函數參數固定值
這裏的做用主要就是變量(函數)持久化,好處就是重複調用的時候不須要再從新建立函數,從而提高執行速度。
爲何要用兩層閉包呢?第一層閉包持久化iterator
函數,調用reduce
和reduceRight
函數避免重複新建函數。第二層閉包保存keys
,index
,length
這些變量。
調用狀況以下,以findIndex爲例,咱們一個個分析它的函數
對每一個元素根據傳入的函數進行計算,若是true,將這個元素放入數組,最後返回數組。
內部仍是先用optimizeCb進行處理函數的綁定和優化,而後執行each,對每一個元素處理。
1.調用values把對象的值轉換成數組返回
2.調用indexOf >=0 判斷是否在給定的數組(或對象中)
3.使用createIndexFinder生成indexOf方法,關鍵點有:
1)根據開始index和dir值,生成循環的條件
2)判斷是否被查找的元素是否是NaN(obj !== obj),若是是的話,對每一個元素調用isNaN判斷是否是NaN,若是有的話,返回true
_.isNaN = function(obj) {
return _.isNumber(obj) && obj !== +obj;
};
通常咱們判斷NaN的方法只須要:a !== a,那麼就是NaN了。
而這裏是爲了同時檢驗出:new Object(NaN)
這個數的類型(toString)是Number,若是+obj的話就轉換成了NaN,知足new Object(NaN) !== NaN
另附對象轉換成數字:
When the [[DefaultValue]] internal method of O is called with hint Number, the following steps are taken:
valueOf
".toString
".首先調用valueOf,若是可執行,返回值,不然調用toString,返回值。
_.invoke(obj, method)
對obj的每一個元素執行method方法,結果組成數組並返回;
若是method是自定義函數,那麼執行method,不然,得到eachvalue[method]並執行。
亂序排列一個數組,幾個關鍵點:
1)返回的是新數組
2)有可能順序是不變的
3)random的
3)核心是:
if (random !== index) shuffle[index] = shuffle[random]
shuffle[random] = set[index];
給函數設置預約義的變量,容許使用佔位符。
核心思想是在partial函數中處理參數,而後返回一個閉包函數,把兩部分參數組裝在一塊兒。
_.throttle(function, wait, [options])
_.after = function(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
};
由於參數也是函數內的一個變量,因此返回的閉包函數對參數的操做也是同一個內存位置,所以直接更新times進行判斷。
_.template(templateString, [settings])
var escapes = {
"'": "'",
'\\': '\\',
'\r': 'r',
'\n': 'n',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
2.而後對捕獲的內容處理,而後組裝成js代碼的字符串形式
對全部匹配的正則都作處理,組裝成一個大的js代碼字符串。
再組裝,增長參數定義,經常使用函數定義等內容在前頭。
最後使用new Function建立render函數,函數的參數有兩個:
第一個參數是傳入的變量對象,若是有setting.variable的話,使用這個字符串做爲變量名,而後模板中都是用這個變量名調用和訪問,速度會快。
若是沒有的話,就命名爲obj,而後經過with(obj) {函數體}的方式來使用這個傳入的數據。