Можно ли автоматически переводить строки в JavaScript?

Я знаю, что могу создать функцию toString() для объекта, чтобы каждый раз, когда он печатался или обрабатывался как строка, он сначала приводил в соответствие объект с этой функцией.

Можно ли сделать это напрямую, чтобы я мог использовать функции объекта String для объекта?

var SomeObject = function(a, b){
    this.a = a;
    this.b = b
}

SomeObject.prototype.toString = function(){
    return [ this.a, this.b ].join(' ')
}

var objInstance = new SomeObject('this', 'that');

console.log(objInstance + '')                // this that
console.log(("" + objInstance).split(''))    // [ 't', 'h', 'i', 's', ' ', 't', 'h', 'a', 't' ]
console.log(objInstance.split())             // error

Можно ли сделать так, чтобы объект "вел себя" как строка, когда к нему вызывается функция String?

Другими словами, я бы хотел, чтобы objInstance.split() имел тот же результат, что и ("" + objInstance).split(''), а также objInstance.length или objInstance.match(/something/) и т.д. И т.д. И т.д.

Ответы

Ответ 1

Вы можете позволить своим объектам наследоваться от String чтобы все строковые методы стали доступны:

class SomeObject extends String {
  constructor(a, b) {
    super(a + " " + b);
    this.a = a;
    this.b = b;
  }
}

var obj = new SomeObject('this', 'that');
console.log(obj.split(""));

Ответ 2

Один из вариантов - вернуть Proxy который проверяет, существует ли свойство в String.prototype, и, если это так, вызывает это свойство со строкой, представляющей объект:

// Declare the proxy handler up front here
// to avoid unnecessary creation of duplicate handler objects
const handler = {
  get(obj, prop) {
    if (obj[prop] !== undefined) {
      return obj[prop];
    }
    const stringMethod = String.prototype[prop];
    if (stringMethod) {
      return stringMethod.bind(obj.a + ' ' + obj.b);
    }
  },
};

const SomeClass = function(a, b) {
  this.a = a;
  this.b = b
  return new Proxy(this, handler);
}

const instance = new SomeClass('this', 'that');

// String methods:
console.log(instance.trim());
console.log(instance.includes('this'));
console.log(instance.includes('somethingelse'));
console.log(instance.split(''));

// Can still assign and retrieve values directly on the object as normal:
instance.foo = 'foo';
console.log(instance.foo);

Ответ 3

Один из вариантов расширения SomeObject, что-то вроде этого.

var SomeObject = function(a, b){
    this.a = a;
    this.b = b
}

SomeObject.prototype.toString = function(){
    return [ this.a, this.b ].join(' ')
};

SomeObject.prototype.split = function() {
   return String.prototype.split.apply(this.toString(), arguments);
};

var objInstance = new SomeObject('this', 'that');

console.log(objInstance + '')                // this that
//console.log(("" + objInstance).split(''))    // [ 't', 'h', 'i', 's', ' ', 't', 'h', 'a', 't' ]
console.log(objInstance.split(''));

Ответ 4

Если я правильно понимаю, вы можете использовать синтаксис распространения для достижения этой цели

 let a = 'this'; let b = 'that'; 
 
const merged = [...a, ...b];

console.log({merged});