通过属性访问者(获取者)传播操作员问题

roy*_*jas 6 javascript babeljs

我很难理解以下代码为何存在一些问题https://jsfiddle.net/q4w6e3n3/3/

注意:所有示例均在chrome版本52.0.2743.116中进行了测试,以防万一

const model = {
  someVal: 'some val',
};


const obs = {
  ...model,
  get accessor() {
    return this.someVal;
  },
}

// Expected: '>>> some val'
// Actual: '>>> undefined'
console.log('>>>', obs.accessor);
Run Code Online (Sandbox Code Playgroud)

但是以下类似的代码片段有效https://jsfiddle.net/q4w6e3n3/5/

const model = {
  someVal: 'some val',
};


const obs = {
  get accessor() {
    return this.someVal;
  },
  ...model,
}

// Expected: '>>> some val'
// Actual: '>>> some val'
console.log('>>>', obs.accessor);
Run Code Online (Sandbox Code Playgroud)

使用babel REPL,我可以看到Object.assign如果在编译代码中可用,可以使用它,当我直接使用它而不是对象散布时,我会遇到相同的问题,并且如果将model 变量放在末尾而不是在开头也可以使用。

这是错误吗?还是预期的行为?

另外,为什么以下代码段也能正常工作?:

const model = {
  someVal: 'some val',
};


const obs = {
  someVal: model.someVal,
  get accessor() {
    return this.someVal;
  },
}

// Expected: '>>> some val'
// Actual: '>>> some val'
console.log('>>>', obs.accessor);
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/q4w6e3n3/6/

我希望它也有同样的问题,但是作为魅力符,getters this关键字是否以某种方式绑定到了添加到它们的对象上?

Coo*_*ham 5

Object.assign不会复制访问器。因此,如果您的摔得痛在您的getter babel之前出现,并且其各种伏都教徒都使用Object.assign,并且访问器不会再次从第二个(也就是类似的)伏都教徒复制到第一个对象上。当您的splat在getter之后时,它将使用getter将splatted属性分配给对象,并保留getter。

参见此处:MDN-Object.assign

相关代码摘录:

**Copying Accessors**
var obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

var copy = Object.assign({}, obj); 
console.log(copy); 
// { foo: 1, bar: 2 }, the value of copy.bar is obj.bar's getter's return value.

// This is an assign function that copies full descriptors
function completeAssign(target, ...sources) {
  sources.forEach(source => {
    let descriptors = Object.keys(source).reduce((descriptors, key) => {
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {});
    // by default, Object.assign copies enumerable Symbols too
    Object.getOwnPropertySymbols(source).forEach(sym => {
      let descriptor = Object.getOwnPropertyDescriptor(source, sym);
      if (descriptor.enumerable) {
        descriptors[sym] = descriptor;
      }
    });
    Object.defineProperties(target, descriptors);
  });
  return target;
}

var copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }
Run Code Online (Sandbox Code Playgroud)