最近在修正stamp的getter/setter问题, 发现我对这个领域依旧一无所知, 虽然经历了前面两篇blog:
我对js对象一无所知
stampit或者是一条出路

如何克隆方法
  • 用bind — 因为bind的原理, 导致只能用一次, 之后再用其他方法设置this都不生效了.
  • new Function配合tostring
  • 正则配合eval
  • apply(null)
  • 据说object.assign也可以???
  • lodash.clone lodash.assign()
  • uncode.extend

是否可以遍历一个对象的所有方法?

  • 查看mdn
  • 查看js应用设计原型扩展原型克隆部分

实际测试了: create是正常的, assign和展开语法有点奇怪, setter会不起作用. 下面是样例代码, 有兴趣可以运行一下.

import { log } from 'mcktools';//使用什么库都可以, 最简单log=console.log也行.
const y = {
  i: '-初始-',
  get info() {
    return `读取一次${this.i}`;
  },
  set info(info) {
    this.i += `设置一次${info}`;
  },
  pp(){
    return 'pp正常';
  },
};
log('0object0 info:', y.info);
y.info = 'y';
log('1object1 info:', y.info);

//测试clone
//测试create
let x=Object.create(y);
log('00x info:', x.info);
x.info='x'
log('11x info:', x.info);
log('11x11 info:', x.pp());

//测试assign
x=Object.assign({}, y);
log('22x info:', x.info);
x.info='x'
log('33x info:', x.info); //这里不对了.
log('44x info:', x.pp());

//测试展开...
x={...y};
log('55x info:', x.info);
x.info='x'
log('66x info:', x.info);  //这里不对了.
log('77x info:', x.pp());
如何克隆getter/setter方法

这个并不是方法克隆的范畴, 因此单独写一篇吧: 我对getter/setter一无所知.

maybe i have find the solution, because i find a big lack of my cognitive concept.

  • getter/setter is not method, it is properties.
    because this doc : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

so we can do like this:

  1. Object.getOwnPropertyDescriptors() or Object.getOwnPropertyNames()
  2. then Object.defineProperties()
回顾一下, 克隆对象属性(可枚举属性)
  • …展开语法
  • Object.assign
  • Object.create
  • Object.keys
  • json.stringify and json.parse
  • for in
后记

underscore的extend为了兼容getter/setter, 已经改成这样了:

_.extend = function(obj) {
    Array.prototype.slice.call(arguments, 1).forEach(function(source) {
        var descriptor, prop;
        if (source) {
            for (prop in source) {
                descriptor = Object.getOwnPropertyDescriptor(source, prop);
                Object.defineProperty(obj, prop, descriptor);
            }
        }
    });
    return obj;
};