使用javascript函数的三种不同方式,但我不知道它的优缺点.有人可以解释这些差异吗?

Ric*_*edt 5 javascript

我有三种方法来制作一个函数并返回它.(也许还有更多?)但我不知道它们之间的差异以及何时使用它们.请有人解释一下.

var test1 = function() {
    var funk1 = function() {
        console.log(1);
    }
    var funk2 = function(msg) {
        console.log(msg);
    }
    return {
        funk1: funk1,
        funk2: funk2
    }
};

var test2 = function() {
    this.funk1 = function() {
        console.log(1);
    }
    this.funk2 = function(msg) {
        console.log(msg);
    }
};

var someThing = test1();
someThing.funk1();
someThing.funk2(2);

var someThing = new test1();
someThing.funk1();
someThing.funk2(2);

var thingElse = new test2();
thingElse.funk1();
thingElse.funk2(2);
Run Code Online (Sandbox Code Playgroud)

Med*_*uly 4

这是模块/库/插件模式

var test1 = function() {
    var funk1 = function() {
        console.log(1);
    }
    return {
        funk1: funk1
    }
};
Run Code Online (Sandbox Code Playgroud)

这就是 OOP(面向对象编程)模式

var test2 = function() {
    this.funk1 = function() {
        console.log(1);
    }
};
Run Code Online (Sandbox Code Playgroud)

不同之处

var t = test1() //function call, t is result of test1 function execution
var t = new test1() //instance initialization, t is instance of test1 class
Run Code Online (Sandbox Code Playgroud)

考虑这个简单的模型

我们有一家制造汽车的制造商,制造商有一些方法,汽车有它自己的方法,我们不会调整制造商的公共属性,但我们仍然无法访问制造商用来制造汽车的技术,所以汽车是黑匣子,暴露了一些公共道具,并且无法调整。

//service for creating/controlling manufactorer
var ManufacturerService = function(companyName) {
    var self = this;
    self.companyName = companyName;

    //encapsulation
    var Car = function(name, number){
        var createdAt = new Date();
        var engineStarts = 0;

        //instance property, doesn't have setter
        Object.defineProperty(this, 'info', {
            get: function(){
                return {
                    name: name,
                    createdAt: createdAt,
                    engineStarts: engineStarts
                }
            }
        });

        //instance method
        this.startEngine = function(){
            //private property, available only on instance, and cannot be extracted
            engineStarts++;

            //reference to ManufacturerService.companyName
            console.log(self.companyName + ' ' + name + ':' + number + ' engine Started');
        }
    }
    var createCar = function(name){
        //check cache/duplication/validation
        //or use custom behavior
        var carNumber = ManufacturerService.genShortUid();
        return new Car(name, carNumber);
    }
    var getName = function(){
        return self.companyName;
    }
    return {
        getName: getName,
        createCar: createCar
    }
};
//static method, this can be overriden by 3rdParty or user 
ManufacturerService.genShortUid = function genShortUid() {
    return ('0000' + (Math.random()*Math.pow(36,4) << 0).toString(36)).slice(-4);
}
Run Code Online (Sandbox Code Playgroud)

用法,ManufacturerService被编写为插件/库,但请注意,Car 模型是完全封装的,这意味着模型对外界完全隐藏

//create a service instance
var VolvoCompany = new ManufacturerService('Volvo');

//access encapsulated Car model by createCar method
//which is available only on instance of service
var Golf = VolvoCompany.createCar('Golf');

//instance method of car Model
Golf.startEngine(); //logs Volvo Golf:vnv6 engine Started

Golf.info
//returns 
Object {name: "Golf", createdAt: Sat Feb 13 2016 17:39:57 GMT+0600 (ALMT), engineStarts: 1}

//try to hack car instance
Golf.info.name = 'test';
Golf.name = 'test';

Golf.info
//returns same object, as Car model doesn't have exported setters
Object {name: "Golf", createdAt: Sat Feb 13 2016 17:39:57 GMT+0600 (ALMT), engineStarts: 1}    

//customize guid generator of ManufacturerService
ManufacturerService.genShortUid = function(){
    return '1111';
}

//reuse same service for another Car model
var Mazda = VolvoCompany.createCar('Mazda');

//instance method of car Model
Mazda.startEngine(); //logs Volvo Mazda:1111 engine Started
Run Code Online (Sandbox Code Playgroud)

概括

ManufacturerService导出的方法数量有限,并且完全开放,但Car实例是完全封装的,甚至不可见

欢迎编辑/建议/评论