Bug Tracker

Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#12745 closed bug (notabug)

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

Reported by: alanoliver999@… 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

Change History (4)

comment:1 Changed 7 years ago by Rick Waldron

Owner: set to Rick Waldron
Status: newassigned

Confirmed

comment:2 Changed 7 years ago by Rick Waldron

Owner: changed from Rick Waldron to elgreg

comment:3 Changed 7 years ago by elgreg

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.

comment:4 Changed 7 years ago by anonymous

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.

Note: See TracTickets for help on using tickets.