最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is there a way to access object properties without referencing the object when provided as a function argument? - S

programmeradmin1浏览0评论

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.

Share Improve this question edited Aug 27, 2019 at 22:48 SomewhereDave asked Aug 27, 2019 at 15:18 SomewhereDaveSomewhereDave 48110 silver badges21 bronze badges 5
  • Why? You will at best save few characters of typing but introduce more potential confusion - what happens if x doesn't have a b 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 writing return 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
Add a ment  | 

6 Answers 6

Reset to default 6

In 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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论