是的,这完全可以用JavaScript实现!
您可以直接跳到结尾查看解决方案,或者阅读以下详细说明。
解决方法
解决方案取决于您如何实现它,因为运行时环境会发挥作用。浏览器实现运行时环境,强制执行它们采用的ECMAScript标准,而Node.js是V8的分支,具有处理标准的自己的模块。
下面,我将提供一个用例并给出两个解决方案以及问题的直接解决方案:
- 通用解决方案,您可以在浏览器和Node.js上实现并使用
- Node.js特定解决方案。
- OP的确切用例的解决方案。
注意:这也将帮助那些正在学习数据结构并尝试进行JavaScript实现的人。
问题
让我们以与OP的用例类似的用例为例,以更好地理解这一点。假设您正在从头开始构建数组数据结构作为自定义xArray
构造函数。为简单起见,我们只实现push
方法,以便我们可以推入一些数据,然后尝试以JavaScript数组构造函数创建对象并打印数组的方式输出结果,当我们console.log
对象或从函数返回它时。
我们还需要静态方法XArray.isArray(input)
,以便我们可以测试对象实例是否与构造函数相同。
如果我们简单地将对象console.log
而不添加解决方案,则会得到类似以下内容的内容:
不良解决方案:
const xArray = new XArray();
xArray.push('a', 'b', 'c', 'd', 'e');
console.log(xArray);
但这不是我们想要的。我们需要像OP的用例中一样使用Object.values(xArray)
,输出需要user.name
而不是整个User { name: 'example', password: 'password' }
因此,这是我们想要的输出:
期望的解决方案:
const returnArr = array => array;
const xArray = new XArray();
xArray.push('a', 'b', 'c', 'd', 'e');
console.log(xArray);
console.log(returnArr(xArray));
console.log(XArray.isArray(xArray));
让我们先构建数组的解决方案,然后简单地将其实现到OP的问题上。
解决方案
解决方案1 - 通用解决方案
适用于所有运行时
我们将通过修改具有log
方法的全局对象来修改构造函数内部的console.log()
。
P.S. - 您可以使用console.log(console)
查看所有控制台方法。
class XArray {
constructor() {
Object.defineProperties(this, {
length: {
writable: true,
enumerable: false,
configurable: false,
value: 0,
},
});
const runtimeConsole = console;
console = {
...console,
log: function (data) {
if (XArray.isArray(data)) runtimeConsole.log(Object.values(data));
else runtimeConsole.log(data);
},
};
}
push(...elements) {
for (const element of elements) {
this[this.length] = element;
this.length++;
}
}
static isArray(array) {
return array instanceof XArray;
}
}
解决方案2: 使用util
模块进行Node.js
翻译
我们将使用node.js
中的util
模块中的util.inspect.custom
符号。
import util from 'util';
class XArray {
constructor() {
Object.defineProperties(this, {
length: {
writable: true,
enumerable: false,
configurable: false,
value: 0,
},
});
}
push(...elements) {
for (const element of elements) {
this[this.length] = element;
this.length++;
}
}
[util.inspect.custom]() {
return Object.values(this);
}
}
解决方案3:解决用户使用情况
您可以使用解决方案1或解决方案2来解决您的使用情况:
解决方案3A:通用解决方案
使用解决方案1
class User {
constructor(name, password) {
this.name = name;
this.password = password;
const runtimeConsole = console;
console = {
...console,
log: function (data) {
if (User.isUser(data)) runtimeConsole.log(data.name);
else runtimeConsole.log(data);
},
};
}
static isUser(user) {
return user instanceof User;
}
}
解决方案3B:使用解决方案2的
Node.js
import util from 'util';
function User(name, password) {
this.name = name;
this.password = password;
[util.inspect.custom]() {
return this.name;
}
}
测试解决方案3A和3B:
const user = new User('example', 'password');
const returnUser = user => user;
console.log(user);
console.log(returnUser(user));
旁注:
import
是 ES6 的一种约定,如果您没有启用 "type": "module"
设置,则默认情况下在 Node.js 中无法使用。这是因为 Node 默认遵循 CommonJS 约定。
如果这让您感到困惑,请替换导入行并使用:const util = require('util');
console.log(user+"")
- epascarelloconsole.log(String(user))
- epascarellotoString
函数不包括password
的值,它怎么类似于一个__repr__
实现呢? - Chris Martinrepr
函数,以查找__repr__
方法。 - Eeveewindow.repr = function (x) { return x.__repr__(); };
来复制Python的行为。虽然不确定为什么这样做,但这并不是Python一个值得称赞的设计决策。 - Chris Martin