Delete A.X VS A.X = Undefined

delete a.x vs a.x = undefined

They are not equivalent. The main difference is that setting

a.x = undefined

means that a.hasOwnProperty("x") will still return true, and therefore, it will still show up in a for in loop, and in Object.keys(). Whereas

delete a.x

means that a.hasOwnProperty("x") will return false

You can't tell if a property exists by testing

if (a.x === undefined)

If you are trying to determine if a property exists, you should always use

// If you want inherited properties
if ('x' in a)

// If you don't want inherited properties
if (a.hasOwnProperty('x'))

Following the prototype chain (mentioned by zzzzBov) Calling delete will allow it to go up the prototype chain, whereas setting the value to undefined will not look for the property in the chained prototypes

var obj = {
x: "fromPrototype"
};
var extended = Object.create(obj);
extended.x = "overriding";
console.log(extended.x); // overriding
extended.x = undefined;
console.log(extended.x); // undefined
delete extended.x;
console.log(extended.x); // fromPrototype

what is difference between using delete keyword , assign undefined value to object literal in javascript?

I see no difference between using delete keyword and assign undefined to target property

The difference is that the property still exists with the value undefined:

"b" in copied // true
"b" in explicitDelete // false

If you don't like the verbosity of delete, you can use a helper function

function omit(obj, ...keys) {
const res = {};
for (const p in obj)
if (!key.includes(p))
res[p] = obj[p];
return res;
}
omit(orignal, "b")

or object destructuring with rest syntax:

const {b:_, ...withoutB} = original;

See also How to omit specific properties from an object in JavaScript, How do I remove a property from a JavaScript object?, How can I clone a JavaScript object except for one key?.

delete operator vs. assigning to undefined or null

V8 developer here. foo.v.cholo = undefined is definitely more efficient than delete foo.v.cholo, because it doesn't change the object's shape (=number, attributes, and internal location of properties). Garbage collection is not affected. It doesn't matter whether you use undefined or null as the zap-out value.

General rule of thumb: avoid delete whenever possible.

This holds in particular when:

  • you have the same set of properties which are sometimes present and sometimes not
  • you care about performance when accessing (any of the) properties on the object in question

If, on the other hand, you have a large set of possible property names which come and go (and are relatively unlikely to reappear), e.g. in a "query string" => "response" cache, then it's probably better to use a Map instead of a plain object.

Difference between assigning an object to undefined and delete

I checked out @mrid and @Amadan's answers and thought a bit, I think I figured it out and came up with a simpler answer, and my explanation in my question is not entirely true.

If I uncomment the first commented line,

var ninja = {};

I'm assigning ninja to an empty object and consequently, I try to run "samurai.yell(4);", I get an error. The reason is because samurai tries to find ninja through its "scope chain" (i.e. some closure magic, which it does find it, but when it tries to find if ninja has a property yell, it's gone, thus the error. though samurai still holds a reference to that anonymous function (which implies it can still run that function), when that anonymous function tries to run ninja.yell(), it couldn't find it anymore, thus the error.

A way to fix this is of course, use the this,

var ninja = {
yell: function (n) {
return n > 0 ? this.yell(n-1) + "a" : "hiy";
}
};

var samurai = { yell: ninja.yell };
var ninja = {};
samurai.yell(4);

Another way is to use a named function expression,

var ninja = {
yell: function foo(n) {
return n > 0 ? foo(n-1) + "a" : "hiy";
}
};

var samurai = { yell: ninja.yell };
var ninja = {};
samurai.yell(4);

And everything should be working.

If I uncomment the second commented line,

delete ninja;

I'm actually not doing anything. delete is only for "removing" properties of an object (you can never delete anything in Javascript, garbage collection handles that), it returns true if the operation is successful, false otherwise. Therefore, "delete" doesn't work on ninja, so simply speaking, I'm not doing anything extra to ninja when I uncomment "delete ninja;", everything still works as normal.

Therefore, you can forget everything I said about "reference" and "delete" in my question, they're not relevant and not true.

Delete a value from a Javascript Object which is retrieved from MongoDB

Alright so I went through the documentation of MongoDB for the query db.collection.findOne(query, projection) and found that the findOne() method returns a document rather than a cursor.

You can refer the docs https://docs.mongodb.com/manual/reference/method/db.collection.findOne

Hence I had to convert it to raw JSON for the delete operation.

So I used

user.toJSON();

And then used the delete method on the Object which worked.

For example

  let json = user.toJSON();
delete json['password'];

One can also use toObject() Method as shown below:

  let json = user.toObject();
delete json['password'];

Why does this code compile without errors in C++17?

(For a thorough walk-through of this topic, see the blog article The fickle aggregate)



Aggregate initialization

Class Ax is an aggregate in C++11, C++14 and C++17, as it has no user-provided constructors, which means that Ax{} is aggregate initialization, bypassing any user-declared constructors, even deleted ones.

struct NonConstructible {
NonConstructible() = delete;
NonConstructible(const NonConstructible&) = delete;
NonConstructible(NonConstructible&&) = delete;
};

int main() {
//NonConstructible nc; // error: call to deleted constructor

// Aggregate initialization (and thus accepted) in
// C++11, C++14 and C++17.
// Rejected in C++20 (error: call to deleted constructor).
NonConstructible nc{};
}

The definition of what is an aggregate class has changed through various standard versions (C++11 through C++20), and these rules can have somewhat surprising consequences. As of C++20, particularly due to the implementation of

  • P1008R1: Prohibit aggregates with user-declared constructors

most of the frequently surprising aggregate behaviour has been addressed, specifically by no longer allowing aggregates to have user-declared constructors, a stricter requirement for a class to be an aggregate than just prohibiting user-provided constructors.



User-provided or only user-declared explicitly-defaulted constructors

Note that providing an explicitly-defaulted (or deleted) definition out-of-line counts as a user-provided constructor, meaning that in the following example, B has a user-provided default constructor, whereas A does not:

struct A {
A() = default; // not user-provided.
int a;
};

struct B {
B(); // user-provided.
int b;
};

// Out of line definition: a user-provided
// explicitly-defaulted constructor.
B::B() = default;

with the result that A is an aggregate, whereas B is not. This, in turn, means that initialization of B by means of an empty direct-list-init will result in its data member b being left in an uninitialized state. For A, however, the same initialization syntax will result in (via aggregate initialization of the A object and subsequent value initalization of its data member a) zero-initialization of its data member a:

A a{};
// Empty brace direct-list-init:
// -> A has no user-provided constructor
// -> aggregate initialization
// -> data member 'a' is value-initialized
// -> data member 'a' is zero-initialized

B b{};
// Empty brace direct-list-init:
// -> B has a user-provided constructor
// -> value-initialization
// -> default-initialization
// -> the explicitly-defaulted constructor will
// not initialize the data member 'b'
// -> data member 'b' is left in an unititialized state

This may come as a surprise, and with the obvious risk of reading the uninitialized data member b with the result of undefined behaviour:

A a{};
B b{}; // may appear as a sound and complete initialization of 'b'.
a.a = b.b; // reading uninitialized 'b.b': undefined behaviour.


Related Topics



Leave a reply



Submit