通过上下文提供对API的访问与通过参数提供对API的访问有什么区别?
What is the difference between offering access to an API through the context or offering it through a parameter?
给定以下API:
SomeAPI = (function() {
var secretKey = 'passw0rd',
foo = 'foo',
bar = 'bar';
return {
use : function(callback) { /* Provide the API to the callback */ }
};
})();
它由几个值组成,最重要的是通过它的use()
公共方法使用,该方法允许用户通过回调来使用API。回调可以通过以下两种方式之一访问API:
1)通过this
callback
是call
ed或appl[i]
ed。使用this
完成API:
SomeAPI.use(function() {
doStuffWith(this.foo);
});
2)通过参数 callback
只是用包含API的参数调用。使用给定的参数来消费API:
SomeAPI.use(function(api) {
doStuffWith(api.bar);
});
这两种模式我都见过。这两者之间有什么实际的区别吗?其中一个可能,而另一个不可能?
两者之间有什么实际的区别吗?其中一个可能,而另一个不可能?
我相信有很多不同之处,但我将尽我所能详细说明最重要的不同之处。
对于第一个示例,将变量赋值给私有对象,然后将私有对象赋值给回调的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调用。
对于第二个示例,我们将每个私有属性的值传递给回调。
这种方法的优点是前一种方法的缺点。此方法锁定所有内容,因此只有您显式允许更改/访问的内容才能更改/访问。
这个方法的缺点是你被锁定在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
});
好的,这告诉我们什么?
- 私有属性实际上是私有的 我们只能通过提供的参数读取私有属性的值。
- 对回调参数所做的任何更改都将而不是保留到下一次API调用。 如果我们在返回的API对象中定义函数来更改私有属性的值,我们可以更改单个值。这些更改将保留到下一次API调用。
最后还有一个例子,它是两者之间的折衷,如果做得好,可以比前面的任何一个例子都更通用。
这个方法的好处是你可以保护你想保护的东西,并选择用户如何访问私有变量。
这个方法的缺点是你必须考虑用户可能会滥用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
});
这个例子告诉我们什么?
- 和之前一样,private还是private
-
this
指向公共对象(返回给OtherAPI的对象) - 我们现在可以设置或获取任何私有属性,只要它们当前存在并且我们没有明确拒绝对该变量的访问。
- 您还可以进一步控制可以设置或检索的私有属性,以及如何进行。
这意味着您的API可能比第一个示例更安全,同时比第二个示例更具灵活性,并且在set和get函数中添加了安全检查,它可以与第二个示例一样安全或更安全。
最后,这一切都取决于你有多信任你的API用户,以及你有多想保护私有属性。
在函数中,this
对象可以引用众多对象中的任何对象。这一切都取决于如何调用给定的函数,以及apply()的第一个参数是什么。
考虑下面的例子:
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- 将JSON传递给Jade,并使用相同的数据进行API访问
- 使用公共API访问(无OAuth)从JavaScript编写Google电子表格
- 仅允许使用 Dropbox API 访问特定网站
- 如何在 AngularJS 中从 API 访问数组数据
- 没有嵌入API访问-iframely
- 通过驱动器API访问文件夹中的文件
- 如何使用 Web 音频 API 访问输出缓冲区
- Facebook API:访问页面对话
- 如何使用图形 API 访问用户喜欢的信息
- 我可以使用Facebook Graph API访问用户的好友状态吗?
- Twitch TV API 访问属性名称值并更新它
- 地图框/传单:有效的GeoJSON生成“未捕获的错误:需要API访问令牌”
- 创建具有 API 访问权限的机场数据库
- 使用 ArcGIS JavaScript API 访问服务器文件
- Firebase简单登录和Twitter API访问
- Trello API访问仅适用于一个人
- 使用javascript SDK或Rest API访问分析数据
- 使用api访问html5视频元素
- 跨域API访问安全性
- 使用Javascript Yammer API访问数据外部网络