Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/405.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Coding style JS库的这种模式有什么问题吗?_Coding Style_Javascript - Fatal编程技术网

Coding style JS库的这种模式有什么问题吗?

Coding style JS库的这种模式有什么问题吗?,coding-style,javascript,Coding Style,Javascript,诚然,我对javascript的内部工作原理知之甚少,但我需要创建一个库,并希望学习(因此在这里提问)。我理解使用闭包和导出到窗口不会污染全局名称空间,但除此之外,它让我有点困惑 (function() { var Drop = window.Drop = function() { var files = []; var add = function(word) { files.push(word);

诚然,我对javascript的内部工作原理知之甚少,但我需要创建一个库,并希望学习(因此在这里提问)。我理解使用闭包和导出到窗口不会污染全局名称空间,但除此之外,它让我有点困惑

(function() {
    var Drop = window.Drop = function() { 

        var files = [];

        var add = function(word) {
              files.push(word);    
              return files;
        }

        return {
            files: files,
            add: add
        }
    }
})()


// All of these seem to be the same?
var a = Drop();
var b = new Drop();
var c = new Drop;

// Each has their own state which is what I want.
a.add("file1");
b.add("file2");
c.add("file3");
  • 为什么三种“初始化”方法都是相同的
  • 到底是什么让他们有能力拥有自己的国家
  • 是否有替代返回语法的方法在Drop上导出这些函数
  • 有没有更好的最佳实践方法来创建这样一个自包含的库
我在网上搜索过,但在这个问题上几乎没有一致性

  • 第一种方法(
    Drop()
    )只是正常调用函数,因此
    是全局对象(
    浏览器环境中的窗口
    )。它完成它的工作,然后返回一个对象,正如您所期望的那样

    第二种方法(
    new Drop()
    )创建一个新的
    Drop
    对象,并在
    this
    设置为该对象的情况下执行构造函数。但是,您不会在任何地方使用
    this
    并返回从对象文本创建的对象,因此
    Drop
    对象将被丢弃,而返回对象文本

    第三种方式(
    newdrop
    )在语义上与第二种相同;这只是句法上的不同

  • 它们都有自己的状态,因为每次调用
    Drop
    ,它都有自己的一组局部变量,不同于任何其他调用
    Drop
    的局部变量

  • 您可以将代码转换为使用普通的
    新的
    语法和原型。这有几个优点:即,只需创建一次
    add
    函数,而不是为每个
    Drop
    调用创建一个函数。修改后的代码可能如下所示:

    function Drop() {
        this.files = [];
    }
    Drop.prototype.add = function(word) {
        this.files.push(word);
        return this.files;
    };
    
    但是,这样做会使您无法在没有
    new
    的情况下调用它。但是,有一个解决方法:您可以将其添加为
    函数下拉列表中的第一行:

    if(!(this instanceof Drop)) {
        return new Drop();
    }
    
    因为当你用
    new
    调用它时,
    这个
    将是一个
    Drop
    ,而当你不用
    new
    调用它时,
    这个
    将不是一个
    Drop
    ,你可以看到
    这个
    是否是一个
    Drop
    ,如果是,继续初始化;否则,请使用
    new
    重新调用它

    还有另一个语义差异。考虑下面的代码:

    var drop = new Drop();
    var adder = drop.add;
    adder(someFile);
    
    您的代码将在这里工作。基于原型的代码不会,因为
    将是全局对象,而不是
    drop
    。这也有一个解决方法:在构造函数中的某个地方,您可以执行以下操作:

    this.add = this.add.bind(this);
    
    当然,如果库的使用者不打算从对象中提取函数,则不需要这样做。此外,您可能需要为没有Function.prototype.bind的浏览器填充
    Function.prototype.bind

  • 不,这完全是口味的问题

    • 为什么三种“初始化”方法都是相同的

    在JavaScript中使用
    new
    调用函数时,函数中的
    this
    值将成为新对象

    但在您的案例中,它们相同的原因是您根本没有使用
    。您正在使用对象文字语法创建一个单独的对象,并返回它,因此
    new
    没有影响


    • 到底是什么让他们有能力拥有自己的国家
    因为每次函数调用都会生成一个新对象,所以每次调用的每个对象都是完全不同的

    分配给对象的函数在每次
    Drop
    调用中重新创建,因此在封闭变量范围上创建闭包。因此,每个调用的
    文件
    数组可以被每个调用中的函数连续访问


    • 是否有替代返回语法的方法在Drop上导出这些函数
    对。将函数和数组分配给
    this
    ,并删除
    return
    语句。但这需要使用
    new
    。或者,将函数放在
    Drop
    .prototype
    对象上,它们将在使用
    new
    创建的所有实例中共享,但将分配给
    的数组保留在构造函数中,以便不共享

    对于引用数组的原型函数,它们将使用
    this.files


    • 有没有更好的最佳实践方法来创建这样一个自包含的库
    JavaScript非常灵活。解决一个问题的方法有很多,每种方法都有自己的优缺点。一般来说,它可以归结为利用闭包、原型继承或两者的组合


    这是一个完整的原型继承版本。另外,没有使用外部的
    (function(){})(
    ,因此我将添加一个变量来利用它

    (function() {
        var totalObjects = 0; // visible only to functions created in this scope
    
        var Drop = window.Drop = function() { 
            this.files = [];
            this.serialNumber = totalObjects++;
        }
    
        Drop.prototype.add = function(word) {
            this.files.push(word);    
            return this.files;
        };
    })();
    

    您可能想了解“javascript闭包”。
    (function() {
        var totalObjects = 0; // visible only to functions created in this scope
    
        var Drop = window.Drop = function() { 
            this.files = [];
            this.serialNumber = totalObjects++;
        }
    
        Drop.prototype.add = function(word) {
            this.files.push(word);    
            return this.files;
        };
    })();