Kli*_*lik 5 javascript jquery jquery-ui object
这段代码最能说明我的困惑.
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
Run Code Online (Sandbox Code Playgroud)
哇,等等,发生什么事了?
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"}
Run Code Online (Sandbox Code Playgroud)
好nativeObj == $( '#tableTab' ) [0] ,这就是我的预期
哇,这很奇怪,为什么不jWrapped == $( nativeObj )呢?
好,jSelector = $( '#tableTab' ) 这也是我的预期
鉴于这些数据,我推断$ .data必须接受本机DOM元素
$( '#tableTab' ).data( 'key' , { test: 78 } );
console.log($( '#tableTab' ).data('key')); // 78
Run Code Online (Sandbox Code Playgroud)
嗯,请原谅我的控制台...不是很酷的男人.
好吧,我庄严困惑和沮丧,我讨厌jQuery和我讨厌JavaScript和我讨厌IE浏览器...好吧,不,我只是讨厌IE浏览器,但这是另一个故事.为什么jQuery表现得那么奇怪?和IE一起玩的太多了我觉得......
我的猜测是它与$ .data在jQuery中的工作方式有关,它实际上并没有将数据附加到元素,而是将数据存储在自己的对象中,并基于解析传递的数据来引用数据它.我找到了一个bug吗?
救命.
我也看了一下jQuery .data()是如何工作的?虽然它确实提供了一些很好的信息,但它仍然没有回答这里发生的事情,这是我真正的问题.虽然它确实证实了我的想法,即没有数据存储在元素中,而是存储在jQuery对象中.
查看 chrome 开发者工具中的源代码,我在 1.9 版本中的第 1564 行附近发现了此注释(此处为 GitHub 源代码,函数内的第 17 行internalData)
// Only DOM nodes need the global jQuery cache; JS object data is
// attached directly to the object so GC can occur automatically
Run Code Online (Sandbox Code Playgroud)
所以,这里发生的事情是,当您传入 时nativeObj,它将把数据存储在 $.cache 中,否则它将把值存储到您传入的 jQuery 对象上。
看看这个小提琴: http://jsfiddle.net/tomprogramming/SNqwh/
我对您原来的示例做了一些更改。第一个是我传入您在顶部设置的对象。第二个是,您在对象中查询一条名为“test”的数据,但该数据永远不会存在 - 您正在存储一个恰好具有名为 test 的属性的对象 - 在“key”属性下。
在日志语句的末尾,我使用面向对象的性质添加了自己的日志语句$.data。每次,我都会得到相同的结果。我的猜测是,它使用每个 jQuery 对象的底层 dom 节点来访问全局缓存,在您的情况下,该缓存的值为{test:34}.
$.data我确实同意这是意外的行为,因为对于新手用户来说,您似乎选择了相同的元素,但我相信这只是和 之间差异的下划线$(selector).data()。后者始终使用底层 dom 节点(因此始终是“正确的”),而前者将使用您传入的 jQuery 对象(如果可用)。
编辑:这个小提琴再次强调了差异。我使用 设置值$(selector).data(),然后使用 再次将其拉出$.data。用于原始对象的“缓存”没有改变(即对象本身),但底层 DOM 节点的全局缓存已经改变。
这里的教训:始终使用 DOM 节点,或者$().data. 这就是“最一致”