Assume you got an object like var obj = {a:'foo',b:'bar'}
you provide to a function function equal(x) { return x.a === x.b};
Is there a way to provide the object argument as scope to remove the object references within the function like so function equal(x) { return a === b};
?
Side note: Syntax preferably works with ECMAScript 5th edition
Rationale: The idea behind the question is to cover cases where the object argument holds many properties {a:'foo',b:'bar',...,z:'baz'}
, which would require repeating the object name quiet often.
Assume you got an object like var obj = {a:'foo',b:'bar'}
you provide to a function function equal(x) { return x.a === x.b};
Is there a way to provide the object argument as scope to remove the object references within the function like so function equal(x) { return a === b};
?
Side note: Syntax preferably works with ECMAScript 5th edition
Rationale: The idea behind the question is to cover cases where the object argument holds many properties {a:'foo',b:'bar',...,z:'baz'}
, which would require repeating the object name quiet often.
-
Why? You will at best save few characters of typing but introduce more potential confusion - what happens if
x
doesn't have ab
property? Should you get it from the global object? – VLAZ Commented Aug 27, 2019 at 15:20 -
2
Are you looking for Destructuring?
({a,b})=>a===b
– user2033671 Commented Aug 27, 2019 at 15:22 - @ProfessorAllman: Destructuring assignment is not supposed to work with 5-th edition. Isn't it? – Yevhen Horbunkov Commented Aug 27, 2019 at 15:28
-
2
Technically you could use a
with {}
statement, which would work for ES5, but it's: 1) not remended at all. 2) more code than actually writingreturn x.a === x.b
. Is there a good reason for this apart from esthetics? – Shilly Commented Aug 27, 2019 at 15:31 - @VLAZ I was thinking about a case where the provided object argument holds many key-value-pairs. In that case, repeating the arguments object name over and over again hinders readability. – SomewhereDave Commented Aug 27, 2019 at 22:36
6 Answers
Reset to default 6In ES6 we can use the destructuring assignment to get the mapping of the key-values in variables:
var obj = {a:'foo',b:'bar'};
//Using ES6 Destructuring syntax
function equal({a, b}) { return a === b};
console.log(equal(obj));
obj = {a:'bar',b:'bar'};
console.log(equal(obj));
You can use with
to change the scope:
function equal(x) {
with(x) { //try to dereference any undeclared variable as a property of x
return a === b; //an implied x.a === x.b
}
}
console.log(equal({a: "foo", b: "bar"}));
console.log(equal({a: "baz", b: "baz"}));
However, using with
is not remended, as it makes things less clear: consider the following examples:
window.a = 1; //a global
function test() {
var a = 2; //a local variable that shadows the global
var foo = {
a: 3 //property of the object
};
with (foo) {
console.log(a); //what is this?
}
}
test();
This example is actually fairly straight forward - the logged result is 3
as with (foo)
changes the context and the first lookup would be foo
itself. However, this can get very confusing, very quickly:
window.a = 1; //a global
function test() {
var foo = {
a: 3 //property of the object
};
with (foo) {
var a = 2; //a local variable that shadows the global
console.log(a); //what is this?
}
console.log(foo); //what about this?
}
test();
Boom, you've now walked into one of the many traps that with
has. I just moved one line down a bit and you'd expect that it still does the same. But it doesn't - with
changes the scope a = 2
now refers to the property of the foo
object. Yes, there is var
in front of it but since you don't get a new functional scope inside with
, that doesn't actually create a new binding but re-uses the one from the current scope. You are actually changing the foo
object with this line, even if you didn't want to. Now, consider your example slightly modified:
window.a = "foo"; //some global defined somewhere
var b = "foo"; //variable that exists in the scope enclosing the function
function equal(x) {
with(x) {
return a === b; // actually might resolve as x.a or a or window.a === x.b or b or window.b;
}
}
var inpleteInput = {a: "foo"};
var emptyInput = {};
console.log(equal(inpleteInput));
console.log(equal(emptyInput));
If you pass in input that doesn't have one of the properties you use inside with
. It bees very hard to figure out what you're actually checking when you're not explicit.
So, while with
technically fulfils your requirement, it's a bad idea to use it. There are many pitfalls about using it and those can very well lead to subtle bugs that could be hard to track down and fix. This is why the usage of the with
statement is not remended.
It would be more useful if you explained why you need it and what problem you're trying to solve, by the way, if it's just a syntax matter, you can use destructuring parameters:
function equal({a, b}) {
return a == b;
}
console.log(equal({
a: 1,
b: 1
}));
If, instead, you want to drop any argument, you can change your function contest using apply
, bind
or call
:
function equal() {
return this.a == this.b;
}
console.log(equal.call({
a: 1,
b: 1
}));
Assuming you can't do anything ES6 I would probably do something like:
function equal(a, b) {
return a === b
}
equal(x.a, x.b);
That way at least equal is reusable.
If you don't know what a
and b
are before run time time, you can access the keys using square bracket notation.
equal(x[var1], x[var2])
Picking the elements from x programmatically is a different problem, which is solved in ES6 to be easily readable using destructuring.
Which would look like const equal = ({a, b}) => a === b
You could also define your own property on the object to do the check for you
const myObject = {a: true, b: false};
Object.defineProperty(myObject, "_IsEqual", {
get: function () {
return this.a === this.b;
}
})
console.log(myObject._IsEqual);
myObject.a = false;
console.log(myObject._IsEqual);
in the example above i don't use reference to the object but this
scope
use distracter in es6 it will help you to ex
const equal = ({a, b}) => a === b
is same the result with destruction in object tell me in mit if it same what you need or noot