当作为函数参数提供时,有没有一种方法可以访问对象属性而不引用对象?

时间:2019-08-27 15:18:30

标签: javascript

假设您有一个类似var obj = {a:'foo',b:'bar'}的对象,该对象提供给函数function equal(x) { return x.a === x.b}; 有没有办法像function equal(x) { return a === b};那样提供对象参数作为作用域以删除函数中的对象引用?

旁注:语法最好与ECMAScript第5版一起使用

合理性:问题的根源在于讨论对象参数拥有许多属性{a:'foo',b:'bar',...,z:'baz'}的情况,这将需要经常安静地重复对象名称。

6 个答案:

答案 0 :(得分:6)

在ES6中,我们可以使用解构分配来获取变量中键值的映射:

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));

答案 1 :(得分:5)

您可以使用with来更改范围:

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"}));

但是,不建议使用with,因为这样会使事情变得不太清楚:请考虑以下示例:

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();

此示例实际上是非常简单的-当3更改上下文时,记录的结果为with (foo),而第一次查找将是foo本身。但是,这很快就会变得很混乱:

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();

景气,您现在走进了with拥有的许多陷阱之一。我只是将一行向下移动了一点,您希望它仍然能执行相同的操作。但事实并非如此-with更改了范围a = 2,现在引用了foo对象的属性。是的,它前面有var,但是由于您没有在with中获得新的功能范围,因此实际上并不会创建新的绑定,而是会重用当前范围中的绑定。即使您不想这样做,实际上您也在用此行更改foo对象。现在,考虑对您的示例进行一些修改:

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 incompleteInput = {a: "foo"};
var emptyInput = {};
console.log(equal(incompleteInput));
console.log(equal(emptyInput));

如果传入的输入内容不具有with内使用的属性之一。当您不明确时,很难弄清您实际上正在检查什么。

因此,尽管with从技术上满足您的要求,但使用它不是一个好主意。使用它存在许多陷阱,这些陷阱很可能导致难以发现和修复的细微错误。这就是为什么不建议使用with语句的原因。

答案 2 :(得分:2)

顺便说一句,如果您解释了为什么需要它以及您要解决什么问题,这将很有用,如果只是语法问题,则可以使用解构参数:

   
function equal({a, b}) {
  return a == b;
}

console.log(equal({
  a: 1,
  b: 1
}));

相反,如果您要删除任何参数,则可以使用applybindcall来更改函数竞赛:

function equal() {
  return this.a == this.b;
}
   
console.log(equal.call({
  a: 1,
  b: 1
}));

答案 3 :(得分:1)

假设您无法做任何ES6,我可能会做类似的事情:

function equal(a, b) {
    return a === b
}

equal(x.a, x.b);

这样至少等于可以重用。

如果在运行时间之前不知道ab是什么,则可以使用方括号表示法访问键。

equal(x[var1], x[var2])

以编程方式从x元素中拾取元素是一个不同的问题,在ES6中已解决该问题,使其易于使用解构方法读取。

看起来像const equal = ({a, b}) => a === b

答案 4 :(得分:1)

您还可以在对象上定义自己的属性来为您做检查

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);

在上面的示例中,我不使用对对象的引用,而是使用this范围

答案 5 :(得分:-1)

在es6中使用分心器将帮助您

const equal = ({a, b}) => a === b

与销毁对象的结果相同 告诉我是否需要或不同意