2

我想实现这个功能:

  1. 我有一个对象var obj = {};
  2. 我在那个 obj 上有三个属性,obj.zero& obj.one&obj.binaryString

    • obj.zero&obj.one是方法,obj.binaryString而是字符串

当我链接属性时,我希望它们将各自的数字添加到binaryString. 例如:

obj.one.zero.zero.one=> 使obj.binaryString=1001

obj.one.zero.one.one.zero=> 使obj.binaryString=10110

我已经实现了上述功能:

function Binary () {
    var obj = { binaryString: '' };

    Object.defineProperty(obj, 'zero', {
        get: function() {
            obj.binaryString += '0';
            return obj;
        }
    });

    Object.defineProperty(obj, 'one', {
        get: function() {
            obj.binaryString += '1';
            return obj;
        }
    });

    return obj;
}

var binary = new Binary();
binary.one.zero.zero.one  // => obj.binaryString becomes '1001'

现在我想注销已完成的binaryString,加上additionalString我用下面的代码完成的:

// placed inside Binary constructor function
Object.defineProperty(obj, 'log', {
    get: function() {
        return function(additionalString) {
            console.log(obj.binaryString + additionalString);
        };
    }
});

所以用这个当前的代码我可以做到这一点:

binary.one.zero.one.zero.one.log(' is the answer');
// logs out `10101 is the answer`

我想要做的是摆脱log和使oneandzero方法可调用或不可调用,以便我可以实现此功能:

binary.one.one.zero.one(' is the result')
// => logs out `1101 is the result`

我怎样才能做到这一点?

我相信它的功能类似于Chalk的工作原理:

chalk.blue.bold('Hello world!');
// `blue` is not invoked here but it adds the color blue to the style

chalk.blue('Hello world!');
// `blue` IS invoked here.  It adds blue to the style and returns the stylized string
4

2 回答 2

3

只需将 obj 设为函数,然后打印您想要的任何内容。

function Binary () {
    var obj = function(msg){ console.log(msg+this.binaryString ) };
    obj.binaryString = ''

    Object.defineProperty(obj, 'zero', {
        get: function() {
            obj.binaryString += '0';
            return obj;
        }
    });

    Object.defineProperty(obj, 'one', {
        get: function() {
            obj.binaryString += '1';
            return obj;
        }
    });

    return obj;
}

var binary = new Binary();
binary.one.zero.zero.one.zero(" is the result ")

于 2017-05-11T18:45:28.433 回答
2

我想指出,您正在做的是一个非常糟糕/危险的想法:滥用读取属性来改变对象本身是在自找麻烦。您现在可能看不到它,但它会以难以发现的错误和复杂模式的形式导致痛苦和心痛。

可以做的是,这不是那么危险,而不是改变对象本身,而是在Binary每次调用#oneor时返回一个新的实例#zero。例如:

function Binary(s) {
  this.binaryString = s || ''
}
Object.defineProperty(Binary.prototype, 'zero', {
  get: function() {
    return new Binary(this.binaryString + '0')
}})
Object.defineProperty(Binary.prototype, 'one', {
  get: function() {
    return new Binary(this.binaryString + '1')
}})

这是 Chalk 采用的方法,并且会更安全且不易出错。

更新

在考虑了您的问题并看到您的问题之后,我认为最好的方法是根本不使用类。您可以使用纯基于函数的方法来解决此问题。它是不可变的,它是安全的,而且我相信它不会那么混乱。这是在 ES5 中:

function bin(str) {
  if(!str) str = ''
  function f(msg) { return str + ' ' + msg }
  return Object.defineProperties(f, {
    zero: {
      get: function() {
        return bin(str + '0')
      },
    },
    one: {
      get: function() {
        return bin(str + '1')
      },
    },
  })
}

如果你可以使用 ES6(又名 ES2015),你可以让它更紧凑:

function bin(str = '') {
  return Object.defineProperties(msg => `${str} ${msg}`, {
    zero: { get() { return bin(str + '0') } },
    one: { get() { return bin(str + '1') } },
  })
}

你会像这样使用它:

bin().one.zero.one.zero('is the answer') // '1010 is the answer'
于 2017-05-11T18:56:02.850 回答