Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spread Properties 与Object.assign的区别 #27

Open
OPY-bbt opened this issue Jan 6, 2020 · 6 comments
Open

Spread Properties 与Object.assign的区别 #27

OPY-bbt opened this issue Jan 6, 2020 · 6 comments

Comments

@OPY-bbt
Copy link
Owner

OPY-bbt commented Jan 6, 2020

No description provided.

@OPY-bbt
Copy link
Owner Author

OPY-bbt commented Jan 6, 2020

Object.assign 将所有可枚举属性的值从一个或多个源对象复制到目标对象

@OPY-bbt
Copy link
Owner Author

OPY-bbt commented Jan 6, 2020

Object.defineProperty(Object, "assign", {
    value: function assign(target, varArgs) { // .length of function is 2
      'use strict';
      if (target == null) { // TypeError if undefined or null
        throw new TypeError('Cannot convert undefined or null to object');
      }

      let to = Object(target);

      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];

        if (nextSource != null) { // Skip over if undefined or null
          for (let nextKey in nextSource) {
            // Avoid bugs when hasOwnProperty is shadowed
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });

@OPY-bbt
Copy link
Owner Author

OPY-bbt commented Jan 6, 2020

Object.assign 会使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。所以无法将setter和getter复制到目标对象中。

例如

const obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

var copy = Object.assign({}, obj); 
console.log(copy); // { foo: 1, bar: 2 } copy.bar的值来自obj.bar的getter函数的返回值

@OPY-bbt
Copy link
Owner Author

OPY-bbt commented Jan 6, 2020

看一下Spread经过babel编译之后的结果

      "use strict";

      function ownKeys(object, enumerableOnly) {
        var keys = Object.keys(object);
        if (Object.getOwnPropertySymbols) {
          var symbols = Object.getOwnPropertySymbols(object);
          if (enumerableOnly)
            symbols = symbols.filter(function(sym) {
              return Object.getOwnPropertyDescriptor(object, sym).enumerable;
            });
          keys.push.apply(keys, symbols);
        }
        return keys;
      }

      function _objectSpread(target) {
        for (var i = 1; i < arguments.length; i++) {
          var source = arguments[i] != null ? arguments[i] : {};
          if (i % 2) {
            ownKeys(Object(source), true).forEach(function(key) {
              _defineProperty(target, key, source[key]);
            });
          } else if (Object.getOwnPropertyDescriptors) {
            Object.defineProperties(
              target,
              Object.getOwnPropertyDescriptors(source)
            );
          } else {
            ownKeys(Object(source)).forEach(function(key) {
              Object.defineProperty(
                target,
                key,
                Object.getOwnPropertyDescriptor(source, key)
              );
            });
          }
        }
        return target;
      }

      function _defineProperty(obj, key, value) {
        if (key in obj) {
          Object.defineProperty(obj, key, {
            value: value,
            enumerable: true,
            configurable: true,
            writable: true
          });
        } else {
          obj[key] = value;
        }
        return obj;
      }

@OPY-bbt
Copy link
Owner Author

OPY-bbt commented Jan 6, 2020

例子:

const obj = {a: 10};
const obj2 = {b: 10};
console.log({...obj, ...obj2 });

结果:

var obj = { a: 10 };
var obj2 = {b: 10};
console.log(_objectSpread({}, obj, {}, obj2));

@OPY-bbt
Copy link
Owner Author

OPY-bbt commented Jan 6, 2020

下面看一个综合的例子

Object.defineProperty(Object.prototype, 'a', {
  set(value) {
    console.log('set called!');
  }
});

const obj = {a: 10};

console.log({...obj});    
// → {a: 10}

console.log(Object.assign({}, obj));    
// → set called!
// → {}

从例子中可以看出使用spread操作符,不会调用到目标对象的setter方法,而是覆盖了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant