Can I construct a JavaScript object without using the new keyword?

后端 未结 15 2594
北海茫月
北海茫月 2020-11-27 16:04

Here is what I\'d like to do:

function a() {
  // ...
}
function b() {
  //  Some magic, return a new object.
}
var c = b();

c instanceof b // -> true
c          


        
相关标签:
15条回答
  • 2020-11-27 16:39

    Someone posted an article by douglas crockford in this question, and it explains exactly what your asking.

    OO Javascript constructor pattern: neo-classical vs prototypal

    0 讨论(0)
  • 2020-11-27 16:41

    Polyfill for new operator:

    function sampleClass() {
        this.cname = "sample";
    }
    
    sampleClass.prototype.getCname = function() {
        return this.cname;
    }
    
    const newPolyfill = function(fname) {
        if (typeof fname !== "function")
        throw Error("can't call new on non-functional input");
    
        let newFun = {};
        newFun.__proto__ = Object.assign(fname.prototype);
        fname.prototype.constructor();
    
        for (let key in fname.prototype) {
            if (typeof fname.prototype[key] !== "function") {
            newFun[key] = fname.prototype[key];
            delete newFun.__proto__[key];
            delete fname.__proto__[key];
           }
        }
    
        return newFun;
    }
    
    let newObj = new sampleClass();
    console.log("new obj", newObj);
    console.log("new cname", newObj.getCname());//sample
    let newPolyObj = newPolyfill(sampleClass);
    console.log("new poly obj", newPolyObj);
    console.log("newPly cname", newPolyObj.getCname());//sample
    console.log(newPolyObj instanceof(sampleClass)) // true
    
    0 讨论(0)
  • 2020-11-27 16:43

    JavaScript objects can be created without using the new keyword.

    For example the following function returns an object without using new keyword

    
    function a(){
        var obj ={};
        obj.name = "hello";
        obj.age = 12;
    
        return obj;
    
    }
    
    0 讨论(0)
  • 2020-11-27 16:44

    Yes you can do this.

    var User = function() {
      var privateMethod = function() {
        alert('hello');
      }
    
      return {
        sayHello : function() {
          privateMethod();
          this.done = true;
        }
      }
    }
    
    var user1 = User();
    

    Is anything wrong with this method?

    0 讨论(0)
  • 2020-11-27 16:44

    For those, who may find this via Google (like me...), I developed the original solution further for a better common usage:

    var myObject = function() {}; // hint: Chrome debugger will name the created items 'myObject'
    
    var object = (function(myself, parent) {  
         return function(myself, parent) {
             if(parent){
                 myself.prototype = parent;
             }
             myObject.prototype = myself.prototype;
             return new myObject();
         };
    })(); 
    
    a = function(arg) {
         var me = object(a);
         me.param = arg;
         return me;
    };
    
    b = function(arg) {
        var parent = a(arg),
            me = object(b, parent)
        ;
        return me;
    };
    
    var instance1 = a();
    var instance2 = b("hi there");
    
    console.log("---------------------------")
    console.log('instance1 instance of a: ' +  (instance1 instanceof a))
    console.log('instance2 instance of b: ' +  (instance2 instanceof b))
    console.log('instance2 instance of a: ' +  (instance2 instanceof a))
    console.log('a() instance of a: ' +  (a() instanceof a))
    console.log(instance1.param)
    console.log(instance2.param)

    0 讨论(0)
  • 2020-11-27 16:46

    Yes. If you don't want to use the 'new' keyword, just use prototype, and return something in your constructor function.

    Using 'new' just tells the constructor functions that:

    1) The 'this' keyword in the constructor function should reference the function itself, not the parent object (as per usual), which would be the window object if this function was declared in the global scope.

    2) For all failed lookups (obj properties not found) on the newly created object/instance, check the original constructor function's prototype property.

    So with new:

        function Point(x, y) {
           this.x = x;
           this.y = y;
        }
        Point.prototype.getDistance = function(otherPoint){
           var Dx = (this.x - otherPoint.x) ** 2;
           var Dy = (this.y - otherPoint.y) ** 2;
           var d = Dx + Dy;
           d = Math.sqrt(d);
           return d
        }
        var pointA = new Point(3, 6);
        var pointB = new Point(5, 8);
        var distanceAB = pointA.getDistance(pointB);
    

    Without new:

        function Point(x, y) {
           let d = Object.create(Point.prototype);
           this.x = x;
           this.y = y;
           return d
        }
        Point.prototype.getDistance = function(otherPoint){
           var Dx = (this.x - otherPoint.x) ** 2;
           var Dy = (this.y - otherPoint.y) ** 2;
           var d = Dx + Dy;
           d = Math.sqrt(d);
           return d
        }
        var pointA = Point(3, 6);
        var pointB = Point(5, 8);
        var distanceAB = pointA.getDistance(pointB);
    

    Try adding removing the 'new' in the the first example, and you'll see the 'this', no longer refers to the constructor function, but the window object instead. You'll be giving your window x and y properties, which proplably isn't what you want.

    0 讨论(0)
提交回复
热议问题