javascript - 通过上下文提供对 API 的访问或通过参数提供对 API 的访问有什么区别?

标签 javascript

给定以下 API:

SomeAPI = (function() {
  var secretKey = 'passw0rd',
      foo = 'foo',
      bar = 'bar';
  return {
    use : function(callback) { /* Provide the API to the callback */ }
  };
})();

它由几个值组成,最重要的是通过其 use() 公共(public)方法使用,该方法允许用户通过回调使用 API。
回调可以通过以下两种方式之一访问 API:

1) 通过这个

callbackcall编辑或 appl[i]编辑。使用 this 即可使用 API:

SomeAPI.use(function() {
  doStuffWith(this.foo);
});

2) 通过参数

callback 只需使用包含 API 的参数进行调用。使用给定参数完成 API 的使用:

SomeAPI.use(function(api) {
  doStuffWith(api.bar);
});
<小时/>

我见过这两种模式的使用。两者之间有什么实际区别吗?其中之一有可能,而另一个则不行?

最佳答案

Is there any practical difference between the two? Something possible with one but not the other?

我确信有很多差异,但我将详细介绍我所能知道的最重要的差异。

对于第一个示例,将变量分配给私有(private)对象,然后将该私有(private)对象分配给回调的 this 值。

这样做的好处是我们实际上传递了对私有(private)对象的引用,因此我们可以更改该对象。

这样做的坏处是,我们实际上传递了对私有(private)对象的引用,因此用户可以随意更改该对象,这从来都不是一件好事。

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

让我们评估一下这向我们展示了什么。

  1. 私有(private)对象实际上是私有(private)的。
  2. this 指的是私有(private)对象。
  3. this 包含所有私有(private)属性。
  4. 对私有(private)对象的任何更改都会保留到下一次 API 调用。
<小时/>

对于第二个示例,我们将每个私有(private)属性的值传递给回调。

此方法的优点是之前方法的失败。此方法会锁定所有内容,因此只有您明确允许更改/访问的内容才能更改/访问。

此方法的缺点是您被锁定在 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
});

好的,这向我们展示了什么?

  1. 私有(private)属性(property)实际上是私有(private)的
  2. 我们只能通过提供的参数读取私有(private)属性的值。
  3. 对回调参数所做的任何更改不会会保留到下一次 API 调用。
  4. 如果我们在返回的 API 对象中定义函数来更改私有(private)属性的值,我们就可以更改各个值。这些更改确实会持续到下一次 API 调用。
<小时/>

最后还有一个示例,可以说是两者之间的折衷方案,如果做得正确,可以比前面的任何一个示例都更加通用。

此方法的好处是您可以保护您想要保护的内容,并选择用户访问私有(private)变量的方式。

此方法的缺点是您确实必须考虑用户可能如何尝试按顺序滥用 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
});

这个例子向我们展示了什么?

  1. 和以前一样,私有(private)就是私有(private)。
  2. this指公共(public)对象(返回给OtherAPI的对象)
  3. 我们现在可以设置获取任何私有(private)属性,只要它们当前存在并且我们没有明确拒绝对该变量的访问。
  4. 您还可以进一步控制可以设置或检索哪些私有(private)属性以及如何进行设置或检索。

这意味着您的 API 可能比第一个示例更安全,同时比第二个示例更灵活,并且通过在 set 和 get 函数中添加安全检查,它可以与第二个示例一样安全或更安全.

最终,这一切都取决于您对 API 用户的信任程度,以及您想要保护私有(private)属性(property)的程度。

关于javascript - 通过上下文提供对 API 的访问或通过参数提供对 API 的访问有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31539056/

相关文章:

Javascript 错误 (IE) : Object doesn't support this property or method

javascript - JS : show textarea field on input change

javascript - 在后台向图表添加图像

javascript - react : Have to constantly update state to make textarea editable

javascript - 用数组中的元素替换字符 "* "的实例 - JavaScript

javascript - 获取可解析时区

javascript - 在javascript中创建结构对象的解决方案

javascript - MVC下如何使用Lightbox

javascript - valueBinding 到数组的内容

javascript - XMLHttpRequest() json并行多线程