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

时间:2015-07-21 12:28:51

标签: javascript

给出以下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

callbackcall ed或appl[i]。使用this

来完成API的使用
SomeAPI.use(function() {
  doStuffWith(this.foo);
});

2)通过参数

只需使用包含API的参数调用

callback。使用给定参数来完成API的使用:

SomeAPI.use(function(api) {
  doStuffWith(api.bar);
});

我已经看过两种模式。这两者之间有什么实际区别吗?可能有一个但不是另一个吗?

2 个答案:

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




让我们来看看它向我们展示的内容。

  1. 私人对象实际上是私有的。
  2. this指的是私人对象。
  3. this包含所有私有属性。
  4. 对私有对象的任何更改都会持续到下一个API调用。
  5. 对于第二个示例,我们将每个私有属性的值传递给回调。

    关于这种方法的好处是前一种方法的垮台。此方法将所有内容锁定,因此只能更改/访问您明确允许更改/访问的内容。

    这种方法的不好之处在于你已经锁定了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. 私有财产实际上是私人财产
    2. 我们只能通过提供的参数读取私有属性的值。
    3. 对回调论据所做的任何更改 会持续到下一次API调用。
    4. 如果我们在返回的API对象中定义函数来更改私有属性的值,我们可以更改单个值。这些更改执行会持续到下一个API调用。
    5. 最后还有一个例子,即两者之间的妥协,如果做得好,可以比前面的任何一个例子更具通用性。

      这种方法的好处在于,您可以保护您想要保护的内容,并选择用户如何访问私有变量。

      关于此方法的不好之处在于,您必须考虑用户如何尝试按顺序滥用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. 与以前相同,私人是私人的。
      2. this引用公共对象(返回给OtherAPI的对象)
      3. 我们现在可以设置获取任何私有属性,只要它们当前存在且我们没有明确拒绝访问该变量。< / LI>
      4. 您还可以进一步控制可以设置或检索的私有属性,以及如何实现。
      5. 这意味着您的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