JavaScript 中带有字符串的原型属性有什么用?



如何在 JavaScript 中将原型属性与字符串变量一起使用。我们的教科书中有一个主题,将原型显示为属性,但缺乏解释并且对其用法感到困惑

以此代码示例作为参考。

let x = 'stackoverflow';
console.log(x.prototype) // gives list of functions
console.log(x.prototype.toLowerCase())) // gives error

String.prototype对象是字符串的方法(即使你处理的大多数字符串都是基元,而不是对象(。如果没有String.prototype.toLowerCase功能,那么"FOO".toLowerCase()将无法工作。这是 JavaScript 的基本原型性质(但有点令人困惑,大多数字符串都是原语;更多内容见下文¹(。

用户空间代码中String.prototype的一个用途是向字符串添加方法:

Object.defineProperty(String.prototype, "initialCaps", {
writable: true,
configurable: true,
value() {
return this.charAt(0).toUpperCase() + this.slice(1);
}
});

console.log("testing".initialCaps());

一般来说,最好避免在库或框架代码中扩展这样的内置原型,因为可能会与其他库等发生冲突。不过,在您自己的应用程序或网页代码中通常没问题。

如果您这样做,请遵循一些最佳实践规则:

  • 如上例所示,使用Object.defineProperty确保添加的方法不可枚举。 不要只执行String.prototype.initialCaps = function() { /*...*/ };,这会创建一个可枚举的属性。因为上面的示例没有说enumerable: true,所以默认情况下该属性是不可枚举的。(不过,内置方法通常是可写和可配置的。

  • 使用将来添加到 JavaScript 时不太可能使用的名称,因此如果以后添加内容,它们不会发生冲突。

  • 如果您使用的是任何第三方代码,切勿扩展Object.prototype。您可能会破坏该代码。

  • 如果您使用的是任何第三方代码,请谨慎扩展Array.prototype您可能会破坏该代码。

通过彻底的测试,您当然可以反对其中任何一个,但是......


¹ 关于原始字符串与字符串对象的事情:

"example"创建一个基元字符串。基元不是对象(理论上(,因此它们没有属性或方法(理论上(。但是大多数基元都有一个与之关联的对象构造函数:字符串String的情况,Number数字等(nullundefined没有关联的构造函数。如果您尝试在基元上使用具有关联构造函数的属性或方法,理论上 JavaScript 引擎会创建一个与该基元等效的对象,然后对该对象执行属性/方法查找。由于该对象的原型是其构造函数上prototype属性中的对象,因此它从该对象获取属性和方法。如果它是一个方法,JavaScript 引擎调用具有原始基元值的方法作为this。(在松散模式下,它将被转换为对象,因此this是调用中的对象;不过,在严格模式下,this可以是基元,并且在对原语进行方法调用的情况下也是如此。

所有这些都是解释"example".toLowerCase()最终调用String.prototype.toLowerCase的很长的方法,this设置为"example"

我在上面说了几次"理论上",因为JavaScript引擎做了很多优化。只要他们的行为符合规范所说的,他们就不必按照规范所说的去做。你可以相当肯定,当你做"example".length"example".toLowerCase()(例如(,没有现代的JavaScript引擎实际上为任何内置对象属性/方法创建一个String对象。(如果您添加了任何内容,并且您的添加处于松散模式,则可能必须这样做。始终使用严格模式的众多原因之一。

最新更新