3

我发现了不同的方法似乎有效。

教科书和互联网上最推荐的方式:

var Person = function() {
    this.age = 23;
}
Tony = new Person();

这似乎也有效:

function Person() {
    this.age = 23;
}
Tony = new Person();

有区别吗?还有一个问题:通常你不能简单地省略括号。在这里是可能的(new Person而不是new Person())。这是因为使用了 new 关键字,对吧?

我刚刚尝试的第三种奇怪方式如下所示:

function Person() {
    return {age: 2};
}
Tony = new Person();
Tony = Person(); // both ways work! It seems that you can leave out 'new' here.

在这里,我没有得到一个带有我的类名称的对象,但我的属性也可以访问,而且它似乎与上述两种方法非常相似。

我应该使用什么以及有哪些技术差异?谢谢!

4

4 回答 4

2

JavaScript 是一种无类语言。类不存在,但对象可以通过使用原型从彼此继承属性。这意味着您不仅限于以类方式实现继承。就个人而言,我喜欢使用受 BackboneJS 启发的方法(代码需要 UnderscoreJS):

var BaseObject = function(){}; //Create a function so that we may use the new operator.
//There may be code in the constructor

BaseObject.extend = function(obj) { //Add a static function to the BaseObject to extend it
    var base = this; //Save a reference for later
    //Create the constructor for the sub object. We need to extend it, so we can't use the base constructor. AFAIK, this is the only way to clone the base constructor, i.e. by creating a new function that calls it
    var SubObject = _.extend(function(){ 
        base.apply(this, arguments); //Call base constructor
    }, this);
    SubObject.prototype=  _.extend({}, this.prototype, obj); //Create new prototype that extends the super prototype, but does not overwrite it.
    return SubObject; //Return the new constructor + prototype
};

这使您可以像这样做很酷的类类似的东西:

var Car = BaseObject.extend({
    speed: 0,
    acceleration: 5,

    accelerate: function(){
        this.speed += this.acceleration;
    }
});

var RaceCar = Car.extend({
    acceleration: 10,
});

var car = new Car();
var raceCar = new RaceCar();
car.accelerate();
raceCar.accelerate();

if(raceCar.speed > car.speed){
    console.log('raceCar won');
}else{
    console.log('car won');
}

有关 JavaScript 继承的更多信息,我强烈建议阅读 Douglas Crockford 的 JavaScript:The Good Parts。

关于你的例子:

1 和 2 之间的差异很小。有关详细信息,请参阅此问题

在 3 中,您只是返回一个对象文字。new 关键字只对函数中的 this 关键字有影响,你没有使用它,所以使用 new 没有效果。有关更多信息,请参阅此问题

于 2013-11-08T09:56:24.140 回答
2

1 和 2 (var x = function vs function x) 非常相似。3是完全不同的东西。

1 和 2 之间的区别与课程无关,之前已在 SO 上询问过(多次)。我认为最完整的答案是这个: https ://stackoverflow.com/a/338053/1669279 简而言之,第一个 x 指向一个匿名函数,一些调试工具可能会遇到问题。第一个可从它定义的行中获得,而第二个可在整个范围内使用。阅读链接的答案以了解详细信息。

第三个“解决方案”根本不是一个类。它只是一个返回对象的函数(可能称为工厂方法)。

从构造函数返回东西不是一个好主意,尤其是return this. 如果你想覆盖创建对象的正常过程(例如实现单例模式),你应该只返回东西。

作为旁注,您应该始终new在实例化类时使用。当您尝试变得聪明并保存角色时,会发生以下情况:

function X () {
  return this;  
}

console.log(X()); // outputs the window object

不带参数调用构造函数后的括号是可选的,但不赞成避免使用它们,因为它会导致代码更加混乱。

总结一下,我通常使用模式1。模式2也可以。

模式 2 的一个问题可能是:

var x = new X(); // works
console.log(x.message); // works, I am X
x.method(); // doesn't work, method hasn't been defined yet

function X() {
  this.message = 'I am X';
}

X.prototype.method = function() {
  console.log(this.message);
};
于 2013-11-08T10:01:48.940 回答
0

这就是我的做法:

    ;(function (window) {
        "use strict";
        //-- Private Vars
        var opt, obj, rm, Debug;

        //-- construtor
        function App(requestedMethod) {
            //-- set up some vars
            if(typeof requestedMethod !== 'undefined') {
                rm = requestedMethod;
            }
            opt = {
                rMethod: (typeof rm !== 'undefined') ? (rm != null) ? rm : false : false
            }
            //-- containe resulable objects
            obj = {}
            //-- call the init method
            this.init();
        }


        /** Public Methods **/

        /**
         * The Init method called on every page load
         */
        App.prototype.init = function () {
            var om = opt.rMethod;
            //-- Once all init settings are performed call the requested method if required 
            if(om) {(typeof App.prototype[om] == 'function') ? App.prototype[om]() : _DB('Call to Method [' + om + '] does not exsist.');}
        };

        /**
         * testmethod
         */
        App.prototype.testmethod = function () {



        };


        /** Private Methods **/

        function PrivateMethod(){

        }
        /**
         *  A console output that should enable to remain enable js to work in IE
         *  just incase i forget to remove it when checking on those pesky IE browsers....
         */
        function _DB(msg){
            if(window.console && window.console.log){
                var logDate = new Date();
                window.console.log('------------------- ' + logDate + ' ----------------------------------');
                window.console.log(msg);
            }
        };


        window.App = App;

    })(window);

然后像这样称呼它:

    <script src="ptha/to/your/app.js"></script>
    <script>$(function() { new App('testmethod'); });</script>

加载代码后,新的 App() 将在所有页面加载数据完成后运行

希望这会有所帮助。要在外部访问它,请将新的添加到 var

 var App = new App('testmethod);

然后您可以访问诸如

    App.testmethod()...
于 2013-11-08T09:49:05.987 回答
-1
var Person = function() {
    this.age = 23;
}

Person 是一个包含(被引用)匿名函数的变量

function Person() {
    this.age = 23;
}

但是在这里你声明了一个名为“Person”的函数

function Person() {
    return {age: 2};
}

因此,您声明了一个返回新静态对象的函数。

最好的方式取决于需要,如果你想声明类使用第二种,而创建模块使用第三种。对于第一种方法看这里:http ://helephant.com/2008/08/23/javascript-anonymous-functions/

于 2013-11-08T09:44:02.360 回答