-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathunderscore.js
199 lines (172 loc) · 4.41 KB
/
underscore.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
(function() {
var root =
(typeof self == "object" && self.self == self && self) ||
(typeof global == "object" && global.global == global && global) ||
this ||
{};
var ArrayProto = Array.prototype;
var push = ArrayProto.push;
var _ = function(obj) {
if (obj instanceof _) return obj;
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
};
if (typeof exports != "undefined" && !exports.nodeType) {
if (typeof module != "undefined" && !module.nodeType && module.exports) {
exports = module.exports = _;
}
exports._ = _;
} else {
root._ = _;
}
_.VERSION = "0.1";
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
// 判断数组或者对象
var isArrayLike = function(collection) {
var length = collection.length;
return (
typeof length == "number" && length >= 0 && length <= MAX_ARRAY_INDEX
);
};
// 需要链式调用的处理函数
var chainResult = function(instance, obj) {
return instance._chain ? _.chain(obj) : obj;
};
// 回调函数,若不存在,返回原值;存在即调用 回调优化函数 optimizeCb
var cb = function(value, context) {
if (_.iteratee !== builtinIteratee) return _.iteratee(value, context);
if (value == null) return _.identity;
return optimizeCb(value, context);
};
// callback 优化,处理 context 存在与否的不同情况,若存在,将this 指向 context
var optimizeCb = function(func, context) {
// 如果没有传入 context,就返回 func 函数
if (context === void 0) return func;
return function() {
return func.apply(context, arguments);
};
};
/**
* 我们自定义的 _.iteratee 函数来处理 value 和 context。默认 iteratee = builtinIteratee, 当然我们也可以自定义
*/
_.iteratee = builtinIteratee = function(value, context) {
return cb(value, context);
};
/**
* 拿到什么返回什么
*/
_.identity = function(value) {
return value;
};
var nativeIsArray = Array.isArray;
/**
* 判断是否为数组
*/
_.isArray =
nativeIsArray ||
function(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
/**
* 判断是否为 对象 或 function
*/
_.isObject = function(obj) {
var type = typeof obj;
return type === "function" || (type === "object" && !!obj);
};
/**
* 判断是否为 function
*/
_.isFunction = function(obj) {
return typeof obj == "function" || false;
};
/**
* 数组或对象遍历方法,并返回修改后的对象或数组
*/
_.map = function(obj, iteratee, context) {
iteratee = cb(iteratee, context);
var length = obj.length,
results = Array(length);
for (var index = 0; index < length; index++) {
results[index] = iteratee(obj[index], index, obj);
}
return results;
};
/**
* 数组或对象遍历方法
*/
_.each = function(obj, callback) {
var length,
i = 0;
if (isArrayLike(obj)) {
length = obj.length;
for (; i < length; i++) {
if (callback.call(obj[i], obj[i], i) === false) {
break;
}
}
} else {
for (i in obj) {
if (callback.call(obj[i], obj[i], i) === false) {
break;
}
}
}
return obj;
};
/**
* 链式调用函数
*/
_.chain = function(obj) {
var instance = _(obj);
instance._chain = true;
return instance;
};
/**
* 获取一个随机数
*/
_.random = function(min, max) {
if (max == null) {
max = min;
min = 0;
}
return min + Math.floor(Math.random() * (max - min + 1));
};
/**
* 获取_的所有属性函数名
*/
_.functions = function(obj) {
var names = [];
for (var key in obj) {
if (_.isFunction(obj[key])) names.push(key);
}
return names.sort();
};
/**
* 字符串倒装
*/
_.reverse = function(string) {
return string
.split("")
.reverse()
.join("");
};
/**
* 混入,将方法集合混入到 _ 中
*/
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) {
var func = (_[name] = obj[name]);
_.prototype[name] = function() {
var args = [this._wrapped];
push.apply(args, arguments);
return chainResult(this, func.apply(_, args));
};
});
return _;
};
_.prototype.value = function() {
return this._wrapped;
};
_.mixin(_);
})();