在空JQuery对象上使用时,为什么JQuery会为.text()、.html()和.val()给出不同的结果?

在空JQuery对象上使用时,为什么JQuery会为.text()、.html()和.val()给出不同的结果?,jquery,html,dom,Jquery,Html,Dom,这实际上不是一个实际问题,而是一个理论问题,但它确实影响了我目前正在编写的一些代码,所以我将继续提问 我使用JQuery解析XML提要并基于返回的XML元素构建页面元素。XML被转换成一个JQuery对象,并且可以很好地访问元素 在检索值时,我会测试元素是否存在,并使用.text()检索其内容。在检查文本之前,我想仔细检查以确保我的选择器返回了一些内容,但注意到一些有趣的事情.text()似乎并不在意。如果选择器返回的JQuery对象为空,.text()在其上使用时将返回“” “很酷”,我想,直

这实际上不是一个实际问题,而是一个理论问题,但它确实影响了我目前正在编写的一些代码,所以我将继续提问

我使用JQuery解析XML提要并基于返回的XML元素构建页面元素。XML被转换成一个JQuery对象,并且可以很好地访问元素

在检索值时,我会测试元素是否存在,并使用
.text()
检索其内容。在检查文本之前,我想仔细检查以确保我的选择器返回了一些内容,但注意到一些有趣的事情
.text()
似乎并不在意。如果选择器返回的JQuery对象为空,
.text()
在其上使用时将返回
“”

“很酷”,我想,直到我意识到
.html()
.val()
的行为是不同的
.html()
返回
null
.val()
返回
未定义的
(在Firefox中…在IE中,它们都返回
未定义的

试一试:

var tempVal = $("#noWayThisIsAnElement");
window.console.log(tempVal.text());          // returns ""
window.console.log(tempVal.html());          // returns null (undefined, in IE)
window.console.log(tempVal.val());           // returns undefined
那么,有人知道这背后的原因吗?

我提问的主要原因是,考虑到他们正在寻找类似类型的值(概念上),您可能会认为“oops,can't do that”的结果是相同的

我想我可以看到
.val()
可能与其他两种不同,因为它可以返回三种数据类型中的一种,但即使删除了它们,
.text()
.html()
都返回字符串,这些字符串表示DOM节点的内容。您可能会认为,当JQuery对象不包含对节点的引用时,它们都会给出类似的结果

所以,我想我现在只需要针对这两种情况编写不同的代码,但是,在此期间,有人有什么见解吗


更新:Kevin B提出了一个关于
.val()
的好观点(实际上,我不知道为什么我没有想到它):D,因为它正在查找未定义的
属性。这与
.attr()
在这种情况下的行为一致


但是,
.text()
.html()
之间的区别仍然存在

它来自于实现:

val() 如您所见,如果没有elem(即空jquery对象),则函数直接
返回:您有一个未定义的

正文()
getText
jQuery.text()
函数的实现

getText = Sizzle.getText = function( elem ) {
    var node,
        ret = "",
        i = 0,
        nodeType = elem.nodeType;

    if ( !nodeType ) {
        // If no nodeType, this is expected to be an array
        for ( ; (node = elem[i]); i++ ) {
            // Do not traverse comment nodes
            ret += getText( node );
        }
    } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
        // Use textContent for elements
        // innerText usage removed for consistency of new lines (see #11153)
        if ( typeof elem.textContent === "string" ) {
            return elem.textContent;
        } else {
            // Traverse its children
            for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                ret += getText( elem );
            }
        }
    } else if ( nodeType === 3 || nodeType === 4 ) {
        return elem.nodeValue;
    }
    // Do not include comment or processing instruction nodes

    return ret;
};
如您所见,对于空对象,我们不会在任何条件下输入
ret
初始化为“”,因此返回“”

html() 在这里,您可以看到它也返回
undefined
。我不知道为什么它会返回空值,但你是对的,我在Chrome上测试了它


如果其他人可以完成这篇文章。

value属性未定义,.val结果有意义。.text()结果有意义,因为.text连接所有选定元素的文本并返回它。由于没有选定的元素,因此连接的文本为“”。至于.html,我不确定。是的,我想
.val()
最有意义
.attr(某些属性)
还返回
未定义的
。至于
.text()
,那么
.html()
不是一个元素所有内容的浓缩吗?请欣赏这个问题。似乎
.text()
才是真正的怪人。否
.html()
不是串联--“如果选择器表达式匹配多个元素,则只有第一个匹配项将返回其html内容。”@BobStein VisiBone-很抱歉出现任何混淆。你是对的,它不是一组选定元素的串联,而是单个选定元素中包含的所有元素的串联(即,其子元素的串联)。是的,我希望它的实现方式更为复杂。出于某种原因,他们决定不在两次通话之间保持行为标准。不过,有趣的是,鉴于高层用户试图检索相当相似的信息,我们可以看到这些调用有多么不同。
jQuery.fn.extend({
    text: function( value ) {
        return jQuery.access( this, function( value ) {
            return value === undefined ?
                jQuery.text( this ) :
                this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
        }, null, value, arguments.length );
    },
getText = Sizzle.getText = function( elem ) {
    var node,
        ret = "",
        i = 0,
        nodeType = elem.nodeType;

    if ( !nodeType ) {
        // If no nodeType, this is expected to be an array
        for ( ; (node = elem[i]); i++ ) {
            // Do not traverse comment nodes
            ret += getText( node );
        }
    } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
        // Use textContent for elements
        // innerText usage removed for consistency of new lines (see #11153)
        if ( typeof elem.textContent === "string" ) {
            return elem.textContent;
        } else {
            // Traverse its children
            for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                ret += getText( elem );
            }
        }
    } else if ( nodeType === 3 || nodeType === 4 ) {
        return elem.nodeValue;
    }
    // Do not include comment or processing instruction nodes

    return ret;
};
html: function( value ) {
return jQuery.access( this, function( value ) {
    var elem = this[0] || {},
        i = 0,
        l = this.length;

    if ( value === undefined ) {
        return elem.nodeType === 1 ?
            elem.innerHTML.replace( rinlinejQuery, "" ) :
            undefined;
    }