How to “properly” create a custom object in JavaScript?

后端 未结 15 2372
被撕碎了的回忆
被撕碎了的回忆 2020-11-21 08:07

I wonder about what the best way is to create an JavaScript object that has properties and methods.

I have seen examples where the person used var self = this<

15条回答
  •  傲寒
    傲寒 (楼主)
    2020-11-21 08:26

    Creating an object

    The easiest way to create an object in JavaScript is to use the following syntax :

    var test = {
      a : 5,
      b : 10,
      f : function(c) {
        return this.a + this.b + c;
      }
    }
    
    console.log(test);
    console.log(test.f(3));

    This works great for storing data in a structured way.

    For more complex use cases, however, it's often better to create instances of functions :

    function Test(a, b) {
      this.a = a;
      this.b = b;
      this.f = function(c) {
    return this.a + this.b + c;
      };
    }
    
    var test = new Test(5, 10);
    console.log(test);
    console.log(test.f(3));

    This allows you to create multiple objects that share the same "blueprint", similar to how you use classes in eg. Java.

    This can still be done more efficiently, however, by using a prototype.

    Whenever different instances of a function share the same methods or properties, you can move them to that object's prototype. That way, every instance of a function has access to that method or property, but it doesn't need to be duplicated for every instance.

    In our case, it makes sense to move the method f to the prototype :

    function Test(a, b) {
      this.a = a;
      this.b = b;
    }
    
    Test.prototype.f = function(c) {
      return this.a + this.b + c;
    };
    
    var test = new Test(5, 10);
    console.log(test);
    console.log(test.f(3));

    Inheritance

    A simple but effective way to do inheritance in JavaScript, is to use the following two-liner :

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

    That is similar to doing this :

    B.prototype = new A();
    

    The main difference between both is that the constructor of A is not run when using Object.create, which is more intuitive and more similar to class based inheritance.

    You can always choose to optionally run the constructor of A when creating a new instance of B by adding adding it to the constructor of B :

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

    If you want to pass all arguments of B to A, you can also use Function.prototype.apply() :

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

    If you want to mixin another object into the constructor chain of B, you can combine Object.create with Object.assign :

    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

    Object.create can be safely used in every modern browser, including IE9+. Object.assign does not work in any version of IE nor some mobile browsers. It is recommended to polyfill Object.create and/or Object.assign if you want to use them and support browsers that do not implement them.

    You can find a polyfill for Object.create here and one for Object.assign here.

提交回复
热议问题