我想知道创建具有属性和方法的JavaScript对象的最佳方法是什么。

我见过有人用var self = this然后用self的例子。在所有函数中确保作用域总是正确的。

然后我看到了使用.prototype来添加属性的例子,而其他人则是内联的。

谁能给我一个适当的例子,一个JavaScript对象的一些属性和方法?


当前回答

A Pattern That Serves Me Well
var Klass = function Klass() {
    var thus = this;
    var somePublicVariable = x
      , somePublicVariable2 = x
      ;
    var somePrivateVariable = x
      , somePrivateVariable2 = x
      ;

    var privateMethod = (function p() {...}).bind(this);

    function publicMethod() {...}

    // export precepts
    this.var1 = somePublicVariable;
    this.method = publicMethod;

    return this;
};

首先,您可以更改向实例添加方法的偏好,而不是向构造函数的原型对象添加方法。我几乎总是在构造函数内部声明方法,因为我经常使用构造函数劫持来实现继承和装饰。

以下是我如何决定哪些声明应该写在哪里:

Never declare a method directly on the context object (this) Let var declarations take precedence over function declarations Let primitives take precedence over objects ({} and []) Let public declarations take precedence over private declarations Prefer Function.prototype.bind over thus, self, vm, etc Avoid declaring a Class within another Class, unless: It should be obvious that the two are inseparable The Inner class implements The Command Pattern The Inner class implements The Singleton Pattern The Inner class implements The State Pattern The Inner Class implements another Design Pattern that warrants this Always return this from within the Lexical Scope of the Closure Space.

以下是为什么这些方法有帮助:

Constructor Hijacking
var Super = function Super() {
    ...
    this.inherited = true;
    ...
};
var Klass = function Klass() {
    ...
    // export precepts
    Super.apply(this);  // extends this with property `inherited`
    ...
};
Model Design
var Model = function Model(options) {
    var options = options || {};

    this.id = options.id || this.id || -1;
    this.string = options.string || this.string || "";
    // ...

    return this;
};
var model = new Model({...});
var updated = Model.call(model, { string: 'modified' });
(model === updated === true);  // > true
Design Patterns
var Singleton = new (function Singleton() {
    var INSTANCE = null;

    return function Klass() {
        ...
        // export precepts
        ...

        if (!INSTANCE) INSTANCE = this;
        return INSTANCE;
    };
})();
var a = new Singleton();
var b = new Singleton();
(a === b === true);  // > true

正如你所看到的,我真的不需要thus,因为我更喜欢Function.prototype.bind(或.call或.apply)而不是thus。在我们的Singleton类中,我们甚至不这样命名它,因为INSTANCE传递了更多的信息。对于Model,我们返回这个,这样就可以使用.call调用构造函数来返回传递给它的实例。多余的是,我们将它分配给变量updated,尽管它在其他场景中很有用。

此外,我更喜欢使用new关键字而不是{括号}来构造对象文字:

Preferred
var klass = new (function Klass(Base) {
    ...
    // export precepts
    Base.apply(this);  //
    this.override = x;
    ...
})(Super);
Not Preferred
var klass = Super.apply({
    override: x
});

如您所见,后者无法覆盖其超类的“override”属性。

如果我确实向类的原型对象添加了方法,我更喜欢对象文字——不管是否使用new关键字:

Preferred
Klass.prototype = new Super();
// OR
Klass.prototype = new (function Base() {
    ...
    // export precepts
    Base.apply(this);
    ...
})(Super);
// OR
Klass.prototype = Super.apply({...});
// OR
Klass.prototype = {
    method: function m() {...}
};
Not Preferred
Klass.prototype.method = function m() {...};

其他回答

基本上在JS中没有类的概念,所以我们使用函数作为与现有设计模式相关的类构造函数。

//Constructor Pattern
function Person(name, age, job){
 this.name = name;
 this.age = age;
 this.job = job;
 this.doSomething = function(){
    alert('I am Happy');
}
}

到目前为止,JS还不知道你想要创建一个对象,所以这里有一个新的关键字。

var person1 = new Person('Arv', 30, 'Software');
person1.name //Arv

参考:专业JS网页开发人员- Nik Z

创建对象

在JavaScript中创建对象最简单的方法是使用以下语法:

Var检验= { A: 5, B: 10, F:函数(c) { 返回。A +这个。B + c; } } console.log(测试); console.log (test.f (3));

这对于以结构化的方式存储数据非常有用。

然而,对于更复杂的用例,创建函数的实例通常更好:

函数测试(a, b) { 这一点。A = A; 这一点。B = B; 这一点。F =函数(c) { 返回。A +这个。B + c; }; } var test = new test (5,10); console.log(测试); console.log (test.f (3));

这允许你创建多个对象共享相同的“蓝图”,类似于你如何使用类在eg。Java。

然而,通过使用原型,这仍然可以更有效地完成。

当一个函数的不同实例共享相同的方法或属性时,您可以将它们移动到该对象的原型中。这样,函数的每个实例都可以访问该方法或属性,但不需要为每个实例复制该方法或属性。

在我们的例子中,将方法f移动到原型中是有意义的:

函数测试(a, b) { 这一点。A = A; 这一点。B = B; } Test.prototype.f =函数(c) { 返回。A +这个。B + c; }; var test = new test (5,10); console.log(测试); console.log (test.f (3));

继承

在JavaScript中进行继承的一个简单而有效的方法是使用以下两行代码:

B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;

这类似于这样做:

B.prototype = new A();

两者之间的主要区别是,A的构造函数在使用Object时不运行。创建,这更直观,更类似于基于类的继承。

你总是可以选择在创建B的新实例时运行A的构造函数,方法是将它添加到B的构造函数中:

function B(arg1, arg2) {
    A(arg1, arg2); // This is optional
}

如果你想将B的所有参数传递给A,你也可以使用Function.prototype.apply():

function B() {
    A.apply(this, arguments); // This is optional
}

如果你想在B的构造函数链中混合另一个对象,你可以combine object。用Object创建。分配:

B.prototype = Object.assign(Object.create(A.prototype), mixin.prototype);
B.prototype.constructor = B;

Demo

function A(name) { this.name = name; } A.prototype = Object.create(Object.prototype); A.prototype.constructor = A; function B() { A.apply(this, arguments); this.street = "Downing Street 10"; } B.prototype = Object.create(A.prototype); B.prototype.constructor = B; function mixin() { } mixin.prototype = Object.create(Object.prototype); mixin.prototype.constructor = mixin; mixin.prototype.getProperties = function() { return { name: this.name, address: this.street, year: this.year }; }; function C() { B.apply(this, arguments); this.year = "2018" } C.prototype = Object.assign(Object.create(B.prototype), mixin.prototype); C.prototype.constructor = C; var instance = new C("Frank"); console.log(instance); console.log(instance.getProperties());


Note

对象。create可以在包括IE9+在内的所有现代浏览器中安全使用。对象。assign不能在任何版本的IE和一些移动浏览器中工作。建议对对象进行填充。创建和/或对象。如果您希望使用它们并支持未实现它们的浏览器,则分配。

你可以为Object找到一个polyfill。建立在这里 还有一个是Object。分配。

当一个人在构造函数调用期间使用关闭“this”的技巧时,是为了编写一个函数,可以被其他不希望调用对象上的方法的对象用作回调。这与“使范围正确”无关。

这是一个普通的JavaScript对象:

function MyThing(aParam) {
    var myPrivateVariable = "squizzitch";

    this.someProperty = aParam;
    this.useMeAsACallback = function() {
        console.log("Look, I have access to " + myPrivateVariable + "!");
    }
}

// Every MyThing will get this method for free:
MyThing.prototype.someMethod = function() {
    console.log(this.someProperty);
};

阅读Douglas Crockford关于JavaScript的文章,您可能会学到很多东西。约翰·瑞西格也很出色。好运!

你也可以试试这个

    function Person(obj) {
    'use strict';
    if (typeof obj === "undefined") {
        this.name = "Bob";
        this.age = 32;
        this.company = "Facebook";
    } else {
        this.name = obj.name;
        this.age = obj.age;
        this.company = obj.company;
    }

}

Person.prototype.print = function () {
    'use strict';
    console.log("Name: " + this.name + " Age : " + this.age + " Company : " + this.company);
};

var p1 = new Person({name: "Alex", age: 23, company: "Google"});
p1.print();

除了2009年接受的答案。如果你可以瞄准现代浏览器,你可以使用Object.defineProperty。

Object.defineProperty()方法直接在上定义一个新属性 对象,或修改对象上的现有属性,并返回 对象。 来源:Mozilla

var Foo = (function () {
    function Foo() {
        this._bar = false;
    }
    Object.defineProperty(Foo.prototype, "bar", {
        get: function () {
            return this._bar;
        },
        set: function (theBar) {
            this._bar = theBar;
        },
        enumerable: true,
        configurable: true
    });
    Foo.prototype.toTest = function () {
        alert("my value is " + this.bar);
    };
    return Foo;
}());

// test instance
var test = new Foo();
test.bar = true;
test.toTest();

要查看桌面和移动兼容性列表,请参见Mozilla的浏览器兼容性列表。是的,IE9+和Safari手机版一样支持。