给出以下API:
SomeAPI = (function() {
var secretKey = 'passw0rd',
foo = 'foo',
bar = 'bar';
return {
use : function(callback) { /* Provide the API to the callback */ }
};
})();
它由几个值组成,最重要的是通过其use()
公共方法使用,该方法允许用户通过回调来使用API。
回调可以通过以下两种方式之一访问API:
this
callback
是call
ed或appl[i]
。使用this
:
SomeAPI.use(function() {
doStuffWith(this.foo);
});
callback
。使用给定参数来完成API的使用:
SomeAPI.use(function(api) {
doStuffWith(api.bar);
});
我已经看过两种模式。这两者之间有什么实际区别吗?可能有一个但不是另一个吗?
答案 0 :(得分:1)
两者之间有什么实际差异吗?可能有一个但不是另一个吗?
我确定有很多,但我会详细说明最重要的差异。
对于第一个示例,将变量分配给私有对象,然后将私有对象分配给回调的this
值。
关于这一点的好处是我们实际上是传递对私有对象的引用,所以我们可以改变该对象。
关于这一点的不好的部分是我们实际上是在传递对私有对象的引用,因此用户可以毫不犹豫地改变该对象,这绝不是一件好事。
SomeAPI = (function() {
var private = {};
private.secretKey = 'passw0rd';
private.foo = 'foo';
private.bar = 'bar';
return {
use : function(callback) { callback.call(private); }
};
})();
console.log(SomeAPI.private);
// undefined
SomeAPI.use(function(){
console.log(this.secretKey, this.foo, this.bar);
// passw0rd foo bar
console.log(this.constructor);
// Object() { [native code] }
console.log(this);
// Object {secretKey: "passw0rd", foo: "foo", bar: "bar"}
this.hello = 'world';
this.foo = 'bar';
this.bar = 'foo';
});
SomeAPI.use(function(){
console.log(this.secretKey, this.foo, this.bar, this.hello);
// passw0rd bar foo world
console.log(this);
// Object {secretKey: "passw0rd", foo: "bar", bar: "foo", hello: "world"}
});

让我们来看看它向我们展示的内容。
this
指的是私人对象。this
包含所有私有属性。对于第二个示例,我们将每个私有属性的值传递给回调。
关于这种方法的好处是前一种方法的垮台。此方法将所有内容锁定,因此只能更改/访问您明确允许更改/访问的内容。
这种方法的不好之处在于你已经锁定了API所定义的内容。
OtherAPI = (function() {
var secretKey = 'passw0rd',
foo = 'foo',
bar = 'bar';
return {
use : function(callback) { callback(secretKey, foo, bar); },
setFoo : function(val) { foo = val },
setBar : function(val) { bar = val }
};
})();
console.log(OtherAPI.foo);
// undefined
OtherAPI.use(function(secretKey, foo, bar){
console.log(secretKey, foo, bar);
// passw0rd foo bar
console.log(this.constructor);
// Window() { [native code] }
foo = 'bar';
bar = 'foo';
console.log(secretKey, foo, bar);
// passw0rd bar foo
});
OtherAPI.use(function(secretKey, foo, bar){
console.log(secretKey, foo, bar);
// passw0rd foo bar
});
OtherAPI.setFoo('bar');
OtherAPI.setBar('foo');
OtherAPI.use(function(secretKey, foo, bar){
console.log(secretKey, foo, bar);
// passw0rd bar foo
});

好的,那是什么告诉我们的?
最后还有一个例子,即两者之间的妥协,如果做得好,可以比前面的任何一个例子更具通用性。
这种方法的好处在于,您可以保护您想要保护的内容,并选择用户如何访问私有变量。
关于此方法的不好之处在于,您必须考虑用户如何尝试按顺序滥用get和set函数
OtherAPI = (function() {
var private = {};
private.secretKey = 'passw0rd';
private.foo = 'foo';
private.bar = 'bar';
private.noaccess = 'No Access!';
return {
use : function(callback) { callback.call(this); },
get : function(prop) {
if(private[prop] && prop != 'noaccess') return private[prop];
return false;
},
set : function(prop, val) {
if(private[prop] && prop != 'noaccess') return (private[prop] = val);
return false;
},
noaccess : function() { return private.noaccess }
};
})();
console.log(OtherAPI.secretKey);
// undefined
console.log(OtherAPI.get('secretKey'));
// passw0rd
OtherAPI.use(function(){
console.log(this.get('secretKey'), this.get('foo'), this.get('bar'), this.get('noaccess'), this.noaccess());
// passw0rd foo bar false No Access!
console.log(this.constructor);
// Object() { [native code] }
// The above object is actually the public scope, not the private scope
this.set('foo', 'bar');
this.set('bar', 'foo');
this.hello = 'world'; // This will be in the public scope
console.log(this.get('secretKey'), this.get('foo'), this.get('bar'), this.get('noaccess'), this.noaccess(), this.hello);
// passw0rd bar foo false No Access! world
});
OtherAPI.use(function(secretKey, foo, bar){
console.log(this.get('secretKey'), this.get('foo'), this.get('bar'), this.get('noaccess'), this.noaccess(), this.hello);
// passw0rd bar foo false No Access! world
});

这个例子向我们展示了什么?
this
引用公共对象(返回给OtherAPI的对象)这意味着您的API可能比第一个示例更安全,同时具有比第二个示例更多的灵活性,并且在set和get函数中添加了安全性检查,它可以比第二个示例更安全或更安全
最后,一切都取决于您对API用户的信任程度,以及您希望保护私有属性的程度。
答案 1 :(得分:0)
在函数中,colModel
对象可以引用来自众多对象的任何内容。这一切都归结为如何调用给定的函数,并且正是apply()的第一个参数。
考虑以下示例:
this
当var fn = function (api) {
doStuffWith(this.foo);
doStuffWith(api.foo);
};
调用以下列方式调用doStuffWith
时,两个fn
调用都会收到相同的参数,相同的字符串对象:
SomeAPI.use(function(api) {
fn.apply(api, [api]);
});
除此之外(没有双关语),完全取决于API命名约定和最佳适用逻辑。两个版本都指向(引用)完全相同的对象,使用的结果会产生更详细,更干净的代码。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this