首页 > 关于javascript语法的一些疑问

关于javascript语法的一些疑问

/*对象复制函数*/
function _shadowClone(e) {
    var t = {};
    for (var n in e) e.hasOwnProperty(n) && (t[n] = e[n]);
    return t;
}

问题一:我知道&&符号可以用在判断和,那么是否此处是表示什么呢?是不是说先执行e.hasOwnProperty,然后执行(t[n]=e[n])呢?

还有这段代码:

/*常规布局*/

Array.prototype.forEach || (Array.prototype.forEach = function(e) {
    var t = this.length;
    if (typeof e != "function") throw new TypeError;
    var n = arguments[1];
    for (var r = 0; r < t; r++) r in this && e.call(n, this[r], r, this)
})

问题二:Array.prototype.forEach || () 是什么意思? 个人推测是先判断数组原型是否有forEach方法,如果没有执行()语句。如果是这样的话,()去掉可以吗?


第一个问题
是的, 相当于

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 值为 nullundefined时, 就会指向默认上下文. 所以传入contextthis指向指定的context, 没有传入的时context 等于 undefined this为默认指向.


a && b :
&&:
当a为真时, 也会接着执行b, 因为也要判断b是否为真
当a为假时, 条件不成立, 所以b不再执行
所以 e.hasOwnProperty(n) && (t[n] = e[n]); 相当于 if (e.hasOwnProperty(n)) { (t[n] = e[n]); }

a || b
||:
当a为真时, 条件成立, 即不在执行b
当a为假时, 还需继续执行b来判断条件是否成立
所以 Array.prototype.forEach || (Array.prototype.forEach = function(e) { 相当于 if (!Array.prototype.forEach) { || Array.prototype.forEach = function(e) { }


这是为了提高代码健壮性的

第一个问题 相当于先判断e.hasOwnProperty(n)是否为true 是则执行后面的代码 (t[n] = e[n])

第二个问题 相当于判断是否存在forEach方法 不存在则执行后面的代码; ||通常用于给参数设置默认值 比如

function foo(arg){
    arg = arg || 'warning';
    //code
}

不过在ES6里面已经可以不用这么麻烦了

//ES6中
function foo(arg = 'warning'){
    //code
}
【热门文章】
【热门文章】