首页 > jQuery问题:在click()方法中使用this

jQuery问题:在click()方法中使用this

jQ版本:jquery-1.7.2.js

HTML:
    <div id="box">test</div>
JS:
<script>
    $(function(){ 
        $('#box').click(function(){ 
            //alert(this.html()); // 报错
            alert(this.innerHTML);// test
            alert($(this).html()); // test
        });    
    });
</script>    

请问一下,经$('#box')获取后,已经得到jQuery对象了,为什么this对应的还是DOM对象,而$(this)却是jQuery对象呢?谢谢!


不管是不是 this, $(xxx) 返回的都是jQuery对象

因为 $(xxx) = jQuery(xxx),如果没有使用 noConflict 的情况下。


jQuery 源码

    dispatch: function( event ) {

        // Make a writable jQuery.Event from the native event object
        event = jQuery.event.fix( event );

        var i, ret, handleObj, matched, j,
            handlerQueue = [],
            args = slice.call( arguments ),
            handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
            special = jQuery.event.special[ event.type ] || {};

        // Use the fix-ed jQuery.Event rather than the (read-only) native event
        args[0] = event;
        event.delegateTarget = this;

        // Call the preDispatch hook for the mapped type, and let it bail if desired
        if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
            return;
        }

        // Determine handlers
        handlerQueue = jQuery.event.handlers.call( this, event, handlers );

        // Run delegates first; they may want to stop propagation beneath us
        i = 0;
        while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
            event.currentTarget = matched.elem;

            j = 0;
            while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {

                // Triggered event must either 1) have no namespace, or
                // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
                if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {

                    event.handleObj = handleObj;
                    event.data = handleObj.data;

                    ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
                            .apply( matched.elem, args );

                    if ( ret !== undefined ) {
                        if ( (event.result = ret) === false ) {
                            event.preventDefault();
                            event.stopPropagation();
                        }
                    }
                }
            }
        }

        // Call the postDispatch hook for the mapped type
        if ( special.postDispatch ) {
            special.postDispatch.call( this, event );
        }

        return event.result;
    }

注意看这一段

ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ).apply( matched.elem, args )

楼主代码当中的click里的回调函数就是在这个时候以apply的方式调用的。
matched.elem就是原生DOM对象。作为回调函数的context,也就是回调函数当中的this
jQuery 就是这么实现的。


这个this是callback中的this,又不是click中的this。所以和$('#box')没关系,具体指什么是取决于click()中这个callback的上下文环境(在这里是调用这个callback的DOM节点,也就是你用document.getElement方法返回的那个)。


简单点,按照下面方式来理解这段代码: $('#box').click(fn)

  1. $('#box')获得的是一个类数组(虽然现在数组中只有一个元素),可模拟成:

var obj = {length:1,"0":domEle}  //其中domEle是id为box的的dom元素.
  1. $('#box').click(fn)做了什么事情呢?其实就相当于:

 for(var i =0;i<obj.length;i++) {
   fn.apply(obj[i],arguments);  //obj[i]不就是一个dom元素么?与$('#box')也就是obj什么关系都没
 }

当然,jquery中具体的处理很复杂,上面的代码只是模拟,便于你理解罢了!


先谢谢各位的热心帮助。看过各位的回答后,我有一些新的认识(不知道对不对)。
1.传入click方法中的是一个回调函数,所以this不是$('#box')。
2.有个问题:回调函数中的this,如果放到js中,应该是指向window吧?为什么在jQ中会指向当前的DOM元素呢?

<body>

<input type="button" value="点击" />

<script>

window.onload=function(){ 
    var oBtn=document.body.children[0];
    oBtn.onclick=function(){ 
        (function(){ 
            alert(this); //window
        })()
    };
};

</script>
</body>


  1. 函数中的this到底指向的什么样的对象,取决于执行上下文的环境

  2. 函数中的this可以通过apply/call/bind等函数方法人为的改变

  3. $('#box').click 方法是jQuery的自定义方法,不是原生的

  4. click回调函数中的this到底指向什么就取决于jQuery对click函数的定义了。换句话说,在实现的时候可以指向DOM元素,也可以指向包装DOM对象后的jQuery对象

  5. 具体指向什么对象,需要参考API说明文档了,(某天可能改为指向jQuery对象了呢:))


this引用的是函数执行的环境对象,比如在全局中调用,this就是window。所以你这个this并不是$("#box")返回的,不是JQ对象,而是调用此函数的div这个dom对象。仔细理解下this。
手机打字好费劲,如果还有不明白的明天开电脑说

评论中的补充:


$('#box')已经返回JQuery对象了啊,所以你后面才能调用click()方法,注意你这一步相当于

var $box = $('#box');
$box.click(function(){
    //TODO
});

而函数执行的环境对象跟你这句代码获得什么对象没关系,本质是在这个DOM上绑定一个事件,
事件触发时,this就只是这个DOM


$(this)并不会改变这个DOM对象,只是进行了一次包装,就像是加了一层外壳,让他变成JQuery对象,从而能够使用JQuery方法,并不是像传入选择器一样去寻找DOM,因此它仍是当前触发此事件的div.box。包装后的JQuery可以还原成DOM对象。
看看下面的代码,通过事件对象获取触发事件的对象:

$('.box').click(function(event){
    console.log(event.target);
    console.log(event.target==this);//非事件冒泡情况下为true
    console.log($(this).get(0)==this);//true
});

你要知道没有jquery 也有js,没有js就没有jquery。 this 是js的东东,函数执行环境中的this 是属于原生js的,怎么能够给你指向jquery对象。 穿上$(this)马甲 才是jquery对象。


因为那个 this#box 所对应的 原生的DOM对象, 没有被 jQuery 包装过, 所以它没有 html 方法.

alert(this === document.getElementById('box')); //true
【热门文章】
【热门文章】