简体   繁体   中英

Extending from another object without using Object.assign (ES6 feature) in JavaScript

Update 1: I didn't mention this earlier, but I was trying to avoid using the new keyword. The Polyfill should work just fine, as well. I should have been clear that I was looking to see if there was an alternative way of writing similar code.


Chris Elliott's article 'Common Misconceptions about Inheritance in JS' illustrates a great way to use closures for data privacy, but does so with the ES6 method Object.assign .

He describes it as:

Object.assign() is a new ES6 feature championed by Rick Waldron that was previously implemented in a few dozen libraries. You might know it as $.extend() from jQuery or _.extend() from Underscore. Lodash has a version of it called assign() . You pass in a destination object, and as many source objects as you like, separated by commas.

It will copy all of the enumerable own properties by assignment from the source objects to the destination objects with last in priority. If there are any property name conflicts, the version from the last object passed in wins.

How can I write this sample without using the ES6 feature Object.assign ?

let animal = {
  animalType: 'animal',

  describe () {
    return `An ${this.animalType} with ${this.furColor} fur, 
      ${this.legs} legs, and a ${this.tail} tail.`;
  }
};

let mouseFactory = function mouseFactory () {
  let secret = 'secret agent';

  return Object.assign(Object.create(animal), {
    animalType: 'mouse',
    furColor: 'brown',
    legs: 4,
    tail: 'long, skinny',
    profession () {
      return secret;
    }
  });
};

let james = mouseFactory();

By writing your own version of object.assign!

function assign(target, sources) {
    // for each object in source, iterate through properties
    // check has own property and add the property to the target 
    // object

    // or just modify in place, too many different ways to do this
    let newTarget = new target();


    for (let i = 0; i < sources.length; i++) {
      for (let key in sources[i]) {
        if (sources[i].hasOwnProperty(key)) {
          newTarget[key] = sources[i][key];
        }
      }
    }
    return newTarget;
}

EDIT: You absolutely don't have to use new - you could also just add them to an empty object.

function assign(sources) {
    // for each object in source, iterate through properties
    // check has own property and add the property to the target 
    // object

    // this is not the important part
    let newTarget = {};


    for (let i = 0; i < sources.length; i++) {
      for (let key in sources[i]) {
        if (sources[i].hasOwnProperty(key)) {
          newTarget[key] = sources[i][key];
        }
      }
    }
    return newTarget;
}

You can actually just use Object.create which is ES5 as described here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

I have rewritten your code in this format, there you go:

var animal = {
  animalType: 'animal',

  describe: function() {
    return 'An ' + this.animalType + ' with ' + this.furColor + ' fur, ' 
      + this.legs + ' legs, and a ' + this.tail + ' tail.';
  }
};

var mouseFactory = function mouseFactory () {
  var secret = 'secret agent';

  return Object.create(animal, {
    animalType: {
        value: 'mouse',
        writable: true
    },
    furColor: {
        value: 'brown',
        writable: true
    },
    legs: {
        value: 4,
        writable: true        
    },
    tail: {
        value: 'long, skinny',
        writable: true        
    },
    profession: {
        value: function () {
          return secret;
        }
    }
  });
};

var james = mouseFactory();

var dave = mouseFactory();
dave.furColor = 'white';

console.log(james.describe());
// An mouse with brown fur, 4 legs, and a long, skinny tail.

console.log(dave.describe());
// An mouse with white fur, 4 legs, and a long, skinny tail.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM