此代码最能说明我的困惑。
var nativeObj, jWrapped, jSelector;
//WIAT = "What I Am Thinking"
nativeObj = $( '#tableTab' ) [0]; //WIAT: unwrap the jQuery object created by the selector and get the native DOM object
jWrapped = $( nativeObj ); //WIAT: wrap up the native DOM object again... should be equal to $( '#tableTab' )
jSelector = $( '#tableTab' ); //WIAT: pass the jQuery object as reference to jSelector variable
// set the data with jQuery's .data method
$.data( jWrapped, 'key', { test: 12 } ); //WIAT: will be equivalant to using $( '#tableTab' ) and should attach the data to it
$.data( $( '#tableTab' ) [0], 'key', { test: 34 } ); //WIAT: using the native DOM obj, it shouldn't work with this, since it doesn't specify in the docs
$.data( $( '#tableTab' ) , 'key', { test: 56 } ); //WIAT: should rewrite the data in the element to { key: { test: 56} }
console.log( $.data ( jWrapped ) ); // {key:{test:12}}
console.log( $.data ( jWrapped[0] ) ); // {key:{test:34}}
console.log( $.data ( nativeObj ) ); // {key:{test:34}}
console.log( $.data ( $( nativeObj ), 'test' ) ); // undefined
console.log( $.data ( $( '#tableTab' ) [0] ) ); // {key:{test:34}}
console.log( $.data ( $( '#tableTab' ) , 'test' ) ); // undefined
哇,等等,发生了什么?
1.为什么我会得到不同的结果?我只使用了1个选择器并引用了一个元素。
2.为什么不是对象引用jWrapped
和来自$( '#tableTab' )
的对象产生相同的结果?
3.此外jWrapped
和jWrapped[0]
正在产生不同的结果?前者是jQuery包装对象,后者是本机DOM对象。基本上它们引用具有不同结果的相同元素!??
//Now let's see what's inside the objects
console.log( $( '#tableTab' ) [0]); // [object HTMLDivElement]
console.log( nativeObj ); // [object HTMLDivElement]
console.log( $( nativeObj ) ); // {0:({}), context:({}), length:1}
console.log( jWrapped ); // {0:({}), context:({}), length:1, jQuery182021025872972076787:{toJSON:(function () {}), data:{key:{test:12}}}}
console.log( $( '#tableTab' ) ); // {length:1, 0:({}), context:({}), selector:"#tableTab"}
console.log( jSelector ); // {length:1, 0:({}), context:({}), selector:"#tableTab"}
好nativeObj == $( '#tableTab' ) [0]
这就是我的预期
哇,这很奇怪,为什么不jWrapped == $( nativeObj )
?
好,jSelector = $( '#tableTab' )
这也是我的预期
鉴于这些数据,我推断$ .data必须接受原生DOM元素,但是
$( '#tableTab' ).data( 'key' , { test: 78 } );
console.log($( '#tableTab' ).data('key')); // 78
对不起,请原谅我......不是很酷的人。
好的,我感到非常困惑和沮丧,我讨厌jQuery,我讨厌Javascript,我讨厌IE ... 好吧,我只是讨厌IE,但这是另一个故事。为什么jQuery表现得那么奇怪?和IE一起玩的太多了我想......
我的猜测是它与$ .data在jQuery中的工作方式有关,并且它实际上并没有将数据附加到元素,而是 将数据存储在自己的对象中,并基于解析传递的数据来引用数据。我找到了一个错误吗?
帮助。
此外,我确实看了How does jQuery .data() work?虽然它确实提供了一些很好的信息,但它仍然没有回答这里发生的事情,这是我真正的问题。虽然它确实证实了我的想法,即没有数据存储在元素中,而是存储在jQuery对象中。
答案 0 :(得分:3)
查看chrome开发人员工具中的来源,我在版本1.9(GitHub source here,第17行,函数internalData
)中的第1564行找到了此评论。
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
所以,这里发生的是,当你传入nativeObj
时,它会将数据存储在$ .cache中,否则它会将值存储到你传入的jQuery对象中。
看看这个小提琴: http://jsfiddle.net/tomprogramming/SNqwh/
我对原始示例进行了一些更改。首先是我传入你在顶部设置的对象。第二个是你在对象中查询一个名为“test”的数据,但是那里不存在 - 你正在存储一个碰巧有一个名为test的属性的对象 - 在“key”的属性下
在日志语句的末尾,我添加了自己的,使用面向对象的$.data
性质。每一次,我都得到相同的结果。我的猜测是它使用每个jQuery对象的底层dom节点来访问全局缓存,在你的情况下,它的值为{test:34}
。
我同意这是出乎意料的行为,因为新手用户认为你选择的是相同的元素,但我相信这只是$.data
和{{1}之间差异的下划线。 }。后者总是使用底层的dom节点(因此总是'正确'),而前者将使用你传入的jQuery对象(如果可用)。
编辑:this fiddle再次强调了差异。我使用$(selector).data()
设置了值,然后使用$(selector).data()
再次将其拉出。用于原始对象的“缓存”没有改变(作为对象本身),但是对于底层DOM节点,全局缓存具有。
此处的课程:始终使用DOM节点或$.data
。这是“最一致的”