更新时间:2023-09-29 18:16:58
第一个问题
是的, 相当于
for (var n in e) {
if (e.hasOwnProperty(n)) {
t[n] = e[n];
}
}
第二个问题:
判断是否Array是否存在forEach方法, 不存在则添加到原型链上.
if (!Array.prototype.forEach) {
Array.prototype.forEach = function() {...}
}
另外括号也不能去掉
额外问题的解答:
首先上面那个代码的目的是当目前js版本没有Array.prototype.forEach 时就自己创建一个, 那么先了解下 forEach的用法:
var arr = ['a', 'b', 'c']
// forEach 接收两个参数 第一个参数是回调函数, 第二个参数`context`时回调函数中this的指向.
arr.forEach(function(item, index, list) { // item为当前元素, index 为当前位置, list为整个数组, 通常等于arr
console.log(item, index, list);
}/*, context*/) // context 就是在回调函数中this的指向.
// 将会输出
// a 0 ['a', b', 'c']
// b 1 ['a', b', 'c']
// c 2 ['a', b', 'c']
在这个函数的内部 this
默认等于 arr, r
等价与index
,r in this
就是判断是否仍然存在项相当于 r in arr
, 在后面的 this[r]
就相当于 arr[r]
(如: r等于1 时就是 arr[1] === 'b'). 而 e.call(...) 相当于 e(this[r], r, this), 只是如果有context, 函数中的this == context
至于 n
很容易解释, 这个 shim 方法中第一个参数是回调函数 function(item, index, list) {} == e == arguments[0] 就是, forEach
接收的第二个参数是绑定回调函数内this的值的对象 e == context
.
不知道你的基础(比如call用法你是否了解), 可能有些点没说清, 如果还有疑问可以提出来.
相关知识
Array.prototype.forEach
Function.prototype.call
再补:
因为第二个参数不常用, 而e其实也可以不传入直接使用 arguments[0]
获取, 只是为了方便取用.
context不会自动生成, JavaScript的函数对参数约束很宽松, 无论多传少传都不会报错, 在调用未传入的参数时参数默认为未定义即undefined
, 因此没传入context时arguments[1] == undefined
; 例:
function foo(a, b) {
console.log(a, b)
console.log(arguments[0], arguments[1], arguments[2])
}
foo(1)
// 输出:
// 1 undefined
// 1 undefined undefined
而 fn.call(context, args)
如果context
值为 null
或undefined
时, 就会指向默认上下文. 所以传入context
就this
指向指定的context
, 没有传入的时context
等于 undefined
this为默认指向.