jQuery是否用`this`变量做了一些魔术?

Ran*_*lue 2 javascript jquery

jQuery让我们习惯了以下this模式:

$(selector).each(function () {
     // do something with `this`
     // `this` iterates over the DOM elements inside `$(selector)`
});
Run Code Online (Sandbox Code Playgroud)

根据这个Crockford谈话(大约15分钟)this,没有用new运算符调用的函数内部的值是全局对象,除了ES5严格模式,在这种情况下它是undefined.

jQuery是否可以通过this将其用于除全局对象之外的其他东西?请指向源代码的特定行.

SLa*_*aks 7

jQuery使用100%非神奇的Function.call方法来调用特定的回调this.

  • [`callback.call(object [i],...`](http://jsapi.info/jquery/1.7/jQuery.each#L660)其中`object [i]`是第i个DOM元素jQuery选择 (3认同)

Zir*_*rak 7

源头修剪和重新调整以符合您的用法:

jQuery.each = jQuery.fn.each = function( object, callback ) {

    for ( var i = 0, length = object.length ; i < length; i++ ) {
        if ( callback.call( object[ i ], i, object[ i ] ) === false ) {
            break;
        }
    }

    return object;
};
Run Code Online (Sandbox Code Playgroud)

这是重要的部分:callback.call.

我的儿子,现在是时候让你满足this价值了.this有一个名称,精确指出它所指的东西 - 容器.this有几个可能的值.

注意:因为它的名字,this是一个难以谈论的价值.因此,无论何时在代码注释或代码说明中,您都会看到单词self(工作名称),它指的是this值.

var o = {
    log : function () {
        console.log( this );
    }
};
o.log(); //will log the object o

function log () {
    console.log( this );
}
//the default enclosing object is the global object - window
//this is the behaviour you observed in Crockford's talk
log();

//the self value is not set in stone. it is evaluated when the function is called
var grass = {
    log : o.log,
    color : 'purple'
};
grass.log(); //will log the object grass
//this is different from languages where self is static. in such languages, doing
// grass.log() would've logged the original object, o, but since self is evaluated
// at runtime, it is set to the now containing object - grass
Run Code Online (Sandbox Code Playgroud)

我们在日常生活中看到的一种现象正在发生变异self.当我看到一个Mudkip并大声喊出"这是蓝色的!"时,尽管我的蓝色调,我并没有提到自己.相反,我宣布了新的价值this(通过指向它).这样的事情可以在js中完成,这就是发生的事情jQuery.each.

它的时间,以满足Function.prototype.applyFunction.prototype.call.他们的行为最好通过一个例子来观察:

grass.speak = function ( message ) {
    //a philosophical conundrum: how does grass talk?
    console.log( this.color + ' ' + message );
};
grass.speak( ' fruit' ); //will log "blue fruit"

var ultraGrass = {
    color : 'maroon'
};

grass.speak.call( ultraGrass, ', hijacked!' ); //will log "maroon, hijacked!"
Run Code Online (Sandbox Code Playgroud)

Function.prototype.call(我call将从现在开始调用它.得到它?调用它... call ... nevermind)接受两个参数:A thisArg和可变长度参数列表.

callapply调用具有指定self值(第一个参数)和参数列表的函数(参数列表中的其余参数,call例如,第二个参数apply).

Function.prototype.call( thisArg, arg0, arg1, arg2, ... );
Function.prototype.apply( thisArg, [arg0, arg1, arg2, ...] );
Run Code Online (Sandbox Code Playgroud)

遵循一个更传统的例子:

function average () {
    console.log( this ); //to see what call and apply actually do

    for ( var i = 0, sum = 0, len = arguments.length; i < len; i++ ) {
        sum += arguments[ i ];
    }
    return sum / ( len || 1 ); //don't want to divide by zero!
}

average( 1, 2, 3, 4, 5 ); //will log the global object, and return 3

average.call( grass, 1, 2, 3, 4, 5 ); //will log the grass object, and return 3
average.apply( grass, [1, 2, 3, 4, 5] ); //will do the same as above

log.call( ultraGrass ); //will log ultraGrass
log.apply( ultraGrass ); //will also log ultraGrass
Run Code Online (Sandbox Code Playgroud)

call和之间的唯一区别apply是apply需要一个参数数组,而调用使用在第一个参数之后作为参数传递给它的所有内容.

回到原来的jQuery代码:

callback.call( object[ i ], i, object[ i ] )
Run Code Online (Sandbox Code Playgroud)

它调用callback函数:

  1. this设置为的值object[ i ],和
  2. 两个参数:iobject[ i ]

欲获得更多信息:

  1. 申请致电 MDN
  2. 申请致电 ES5规范