Skip to main content

Bug Tracker

Side navigation

#12745 closed bug (notabug)

Opened October 16, 2012 02:51PM UTC

Closed October 16, 2012 03:44PM UTC

Last modified October 17, 2012 05:42AM UTC

Changes to "this" within jQuery.each() are not persisted after iterating a plain JS object

Reported by: alanoliver999@gmail.com Owned by: elgreg
Priority: undecided Milestone: None
Component: unfiled Version: 1.8.2
Keywords: Cc:
Blocked by: Blocking:
Description

Bug report.

When jQuery.each() is used to iterate the properties of a very simple plain JS object, changes made to the property via "this" are not persisted back into the original object.

See this jsfiddle for a demonstration exhibiting the problem. I tried to change the value of a property via "this", but the original value re-appeared once that iteration completed.

A limited workaround is possible by using an immediate function and making changes directly to the original object from within each iteration using just the iteration index key, but this would be much harder if a proper callback function was required (because "this" is relied upon in such cases so that functions can reside outside the current context).

The documentation states that "this" can be used to save changes to the object, and is also further confirmed by examples within the Wiki posts at bottom of documentation page.

The issue exists at least when using Google Chrome v23 and v24, and IE9 running on Vista, and on the native browser in Android (Gingerbread 2.3.5). My peers on jQuery forum have also confirmed the issue.

I have tried jQuery Core versions 1.8.2 back to 1.6.4. All exhibit the problem.

I recommend fixing this bug in next scheduled release because it breaks expected behaviour (all callback functions should utilise "this" to represent the current active item).

Best wishes,

Alan

Attachments (0)
Change History (4)

Changed October 16, 2012 03:27PM UTC by rwaldron comment:1

owner: → rwaldron
status: newassigned

Confirmed

Changed October 16, 2012 03:28PM UTC by rwaldron comment:2

owner: rwaldronelgreg

Changed October 16, 2012 03:44PM UTC by elgreg comment:3

resolution: → notabug
status: assignedclosed

The issue in your example is not that changes aren't persisted, but rather that "this" inside of a $.each refers to the ''value'' of each entry in the collection. This is how jQuery has always worked and is generally how iterator functions work.

"The value can also be accessed through the this keyword, but Javascript will always wrap the this value as an Object even if it is a simple string or number value."

In the OP's example, this[index] would translate to 'please change this'['testA'] which doesn't exist.

Here's an example where this is changed because it's a collection of collections:

http://jsfiddle.net/elgreg/96XDz/14/

Here's underscore's _.each where context is window: http://jsfiddle.net/elgreg/zaErz/

Suggest just using the original object per OP (obj[index]) or $.proxy(obj[index]) if a callback situation is required.

Changed October 17, 2012 05:42AM UTC by anonymous comment:4

Thank you. I fully agree with your findings and apologize for my misunderstanding. The documentation does indeed repeatedly mention wrapping within an object. It simply didn't register, as I have never come across this odd behavior before and, in my mind, my property __was__ already wrapped in an object (obj). I do now see the distinction, so I shall use jQuery.each() for complex objects and use plain old JavaScript for simple plain objects. Since regards, Alan.