假设您有一个类似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'}
的情况,这将需要经常安静地重复对象名称。
答案 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
}));
相反,如果您要删除任何参数,则可以使用apply
,bind
或call
来更改函数竞赛:
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);
这样至少等于可以重用。
如果在运行时间之前不知道a
和b
是什么,则可以使用方括号表示法访问键。
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
与销毁对象的结果相同 告诉我是否需要或不同意