-
-
Notifications
You must be signed in to change notification settings - Fork 291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefer Reflect.deleteProperty
over the delete
keyword in ES2015?
#14
Comments
Hmm, this is a difficult one. I think I'd prefer |
Some discussion on my tweet: https://twitter.com/sindresorhus/status/634680039838117888 |
Assuming I would like to use delete functionality somewhere in my code (because it is something I would try to avoid), then I think I would prefer to use My reason is that I believe However, |
One thing makes me lean towards |
I have mixed feeling about this. I agree that In my benchmarks, polyfilled I say don't add this until there is support in the latest browsers. We wouldn't want to force xo users to write code which requires a polyfill to run. |
I'm for Unless |
@rauschma: Unless I'm mistaken, From the
From the
Which means I'd almost prefer Unless I check all of my 'use strict';
var obj = {};
Object.defineProperty(obj, 'foo', {
value: 1234
});
delete obj.foo;
I'm a fail as fast as possible kind of guy, and |
o/ @sindresorhus & co. I'm the one that suggested and subsequently wrote the The main reason is that its more an explicit call - where delete can have any identifier passed to it, |
@keithamus but If you want to act upon what exactly happened when trying to delete, wouldn't you want the specificity of |
I personally prefer the As for the |
@Qix- sorry I didnt really articulate myself properly toward the end of that. Let me rectify that:
That's just the states if the reference is a property reference (e.g. Now if you just call if (typeof target !== 'object') {
console.warn('Target should be an object, try again');
return;
}
var deleted = Reflect.deleteProperty(target, key);
if (!deleted) {
console.warn('Oops, didnt delete!');
} "use strict";
if (typeof target !== 'object') {
console.warn('Target should be an object, try again');
return;
}
try {
delete target[key];
} catch(e) {
if (e.constructor.name === 'ReferenceError') {
console.warn('Hmm, something weird happened with super references or some stuff');
} else if (e.constructor.name === 'TypeError') {
console.warn('Oops, didnt delete');
}
} // no-strict
if (typeof target !== 'object') {
console.warn('Target should be an object, try again');
return;
}
try {
var deleted = delete target[key];
if (deleted) {
console.warn('Oops, didnt delete');
}
} catch(e) {
if (e.constructor.name === 'ReferenceError') {
console.warn('Hmm, something weird happened with super references or some stuff');
}
} The point of the above is that despite So you could stipulate a rule like so:
But at that point you're mixing and matching two APIs that do the same thing, but with different return values, and may as well stick with one - so do you never care about the deleted property (and so use |
@keithamus You bring up good points, but the way I see it is that when I call 'use strict';
delete xyz.foo; // throws; must mean there's a bug in my code somewhere whereas if (!Reflect.deleteProperty(xyz, 'foo')) {
throw new Error('Welp, there\'s a bug, Jim.)';
} Further, |
Interesting topic. I think this should be treated only as a preference, never defining a big constraint about imposing one or other operation, mostly because, according to MDN, From other side, removing members from objects has evident performance downgrades in V8 since it enforces the VM to break hidden classes benefits. Maybe that could be noticed to the user as well. Here're some performance tests: |
Side note: Glad to see JS perf back up. @h2non The first test does functionally different things. Just pointing that out. |
@h2non granted, still pointing out that Also, those tests are flawed; they should be using the After section to reset the variable, not contaminating test results via making function calls. |
@Qix- That's the point, since technically in ES there's no way to strictly remove own non-inherited properties without using the So the goal here is how to achieve a similar approach without using that operator, and therefore without losing the benefit of hidden classes in V8 (taking into account the nature of C++, objects are usually internally mapped into classes which cannot vary at runtime), which is one significant design performance feature of the engine. Setting "removed" members to Another common approach is remove properties by clone, omitting those fields to delete during the copy, but in most cases the performance cost of copying the whole object has not too much performance gain, actually. Obviously, we're covering very specific optimization details only justifiable in particular scenarios, so you've to consider the tradeoffs of each approach, also based on the specific use case, but in my experience, in most cases the significant part of an object is its value, not its key, so the key could remain, but pointing to nothing. |
Doing a |
So the reasoning seems to be about a desire to force complexity over long-established conventions for the sake of specificity. I don't have an especially strong opinion on this. However, in case it helps others make a decision: delete window // false
delete this // true
this === window // true
delete this // true
delete localStorage // true
delete localStorage.length // true
typeof localStorage // 'object'
typeof localStorage.length // 'number'
delete Function // true
typeof Function // 'undefined' |
@barneycarroll were you in strict mode? ;) |
@qix |
@barneycarroll that's why. Most of those would result in Even if you had a |
Thanks for the feedback all. Personally, I'll stick with using the |
ESLint 1.2.0 came with a new ES2015 rule called
prefer-reflect
that suggestsReflect
where applicable.The only method I'm unsure about is preferring
Reflect.deleteProperty
over thedelete
keyword.xojs/eslint-config-xo@8b16afc#diff-52091282b1c3f2e056102160d5de3ec2R35
Thoughts?
Also, does it make sense to use Reflect over the other methods, like
call
,apply
, etc?The text was updated successfully, but these errors were encountered: