V-1.8.2 underscore源碼解析(二)
if(typeof exports !== "undefined") {
if(typeof module !== "undefined" && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
root._ = _;
}
將上面定義的 _
局部變量賦值給全局對象中的 _
屬性
即客戶端中 window._ = _
服務端(node)中 exports._ = _
在node.js上和瀏覽器用戶端上 _ 是一個全局變量
_.VERSION = "1.8.2";
當前的版本
var optimizeCb = function(func, context, argCount) {
// 如無this指向,則返回原函數
if(context === void 0) return func;
switch(argCount == null ? 3 : argCount) {
case 1:
return function(value) {
return func.call(context, value);
};
case 2:
return function(value, other) {
return func.call(context, value);
};
case 3:
return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4:
return function(value) {
return func.call(context, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
void 運算符能對給定的表達式進行求值,然後返回 undefined而且能節省字節,不少js工具在壓縮過程中,正是用void 0 代替undefined。
對回調函數的優化,主要用來改變函數的執行環境和執行函數,對不同的參數個數做不同的處理,優化js引擎,避免使用arguments
使用call和apply函數來綁定執行上下文。
根據是否有參數和參數的不同類型,返回不同的函數或值
var cb = function(value, context, argCount) {
// 根據不同的value屬性,返回調用不同的函數
if(value == null) return _.identity;
if(_.isFunction(value)) return optimizeCb(value, context, argCount);
if(_.isObject(value)) return _.matcher(value);
return _.property(value);
};
_.iteratee = function(value, context) {
return cb(value, context, Infinity);
};
var createAssigner = function(keysFunc, undefinedOnly) {
return function(obj) {
var length = arguments.length;
// 當返回的函數參數的個數爲0或者1或者爲null的時候
if(length < 2 || obj == null) return obj;
// 當返回的函數參數個數大於1的時候
for(var index = 1; index < length; index++) {
// var一個變量source接收arguments[1],source爲對象參數;
var source = arguments[index],
// 將第二個開始的對象參數的鍵值對作爲參數傳入第一個參數函數
// 返回一個數組
keys = keysFunc(source),
l = keys.length;
for(var i = 0; i < l; i++) {
var key = keys[i];
// 當obj[key]爲undefined的時候才覆蓋,即如果有相同的key值,則
// 取首次出現的value值
if(!undefinedOnly || obj[key] === void 0)
obj[key] = source[key];
}
}
return obj;
};
};
// An internal function for creating a new object that inherits from another.
// 創建一個繼承自另外一個對象的新對象,原型繼承
var baseCreate = function(prototype) {
// 如果prototype不是一個對象,返回一個新對象
if(!_.isObject(prototype)) return {};
// es5的一種新的對象創建方式,如果瀏覽器支持這個屬性,則執行這一步,創建一個新對象
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];
};
};
// 閉包
// 返回一個函數,如果obj是null或者undefined,返回undefined,否則返回obj[key]即
// key對象對應的屬性值
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
// 返回2的53次冪-1
var isArrayLike = function(collection) {
var length = collection != null && collection.length;
// 獲取參數的長度,判斷類數組擁有length屬性,並且限定長度區間
return typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX;
// 利用短路優化性能,返回length的類型爲數字,長度在0-2^53-1之間
};
// isArrayLike判 斷collection是否是一個類數組或者對象
// Helper for collection methods to determine whether a collection
// should be iterated as an array or as an object
// Math.pow(2, 53) - 1 是 JavaScript 中能精確表示的最大數字