使用哪种方法在JavaScript中定义类

使用哪种方法在JavaScript中定义类,javascript,class,Javascript,Class,我发现了不同的方法似乎是有效的 教科书和互联网上推荐的方式主要有: var Person = function() { this.age = 23; } Tony = new Person(); 这似乎也可行: function Person() { this.age = 23; } Tony = new Person(); 有区别吗?还有一个问题:通常你不能简单地省略括号。这里是可能的(newperson而不是newperson())。这是因为使用了新的关键字,对吗 我刚才

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

教科书和互联网上推荐的方式主要有:

var Person = function() {
    this.age = 23;
}
Tony = new Person();
这似乎也可行:

function Person() {
    this.age = 23;
}
Tony = new Person();
有区别吗?还有一个问题:通常你不能简单地省略括号。这里是可能的(
newperson
而不是
newperson()
)。这是因为使用了新的关键字,对吗

我刚才尝试的第三种奇怪的方法如下:

function Person() {
    return {age: 2};
}
Tony = new Person();
Tony = Person(); // both ways work! It seems that you can leave out 'new' here.
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');
}
在这里,我没有得到一个名为我的类的对象,但是我的属性也是可访问的,它似乎与上述两种方法非常相似

我应该使用什么?技术上的区别是什么?谢谢大家!

var Person = function() {
    this.age = 23;
}
Person是包含(被引用)匿名函数的变量

function Person() {
    this.age = 23;
}
但这里您声明了一个名为“Person”的函数

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

最好的方法取决于需要,如果要声明类,请使用第二种方法,而创建模块时使用第三种方法。关于第一种方法,请看这里:

这是我的方法:

    ;(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.testmethod()...

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

这让你可以做一些很酷的课程,比如:

function Person() {
    return {age: 2};
}
Tony = new Person();
Tony = Person(); // both ways work! It seems that you can leave out 'new' here.
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没有任何效果。有关更多信息,请参见1和2(var x=函数vs函数x)非常相似。3是完全不同的事情

1和2之间的差异与类无关,并且之前已经被问过(多次)。我认为最完整的答案是: 简言之,第一个x指向一个匿名函数,一些调试工具可能会遇到这个问题。第一个在定义它的行中可用,而第二个在整个范围中可用。阅读链接答案了解详细信息

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

从构造函数返回内容不是一个好主意,尤其是
返回这个
。只有在希望覆盖创建对象的正常过程(例如实现单例模式)时,才应该返回内容

另外,在实例化类时,应该始终使用
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);
};

非常感谢。除了技术上的区别之外,还有实际的区别吗?使用第二种方法,使用chromeThank开发工具更容易找到内存泄漏,您可以共享。你能解释一下你对
子对象的定义吗?我不太了解
this
的两个版本与
base.apply()
的关系。虽然我知道每一个单独的意思,但上下文在某种程度上是混乱的。尽管如此,结果还是很好的。1和2基本相同(差别很小)。3是一个返回值的函数(本例中为object literal)。函数可用于返回值或作为构造函数创建对象实例(使用new关键字)。有关构造函数和原型的所有信息可在此处找到:
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);
};