string.length其实不是JavaScript中的一个方法吗?

Isn't string.length actually a method in JavaScript?

我想更好地理解当我找到一个字符串的长度时实际发生了什么。我尝试查看 W3、ECMA 和 V8 Ignition 网站,但运气不佳。

我一直在阅读 'JavaScript treats primitive values as objects when executing methods and properties.' 但是,我似乎无法弄清楚这是怎么发生的。如果我在原语上调用 method/property,我假设它被 Ignition 解释为对象,那么 String class 是否需要在某个时候调用函数来迭代字符串?我觉得 myString.length 应该被称为方法,String.length 可以 MAYBE 被称为 属性,这取决于“属性" 及其发现方式。

基本上,我不明白为什么它被吹捧为属性,如果它似乎不是固有的并且必须是fetched/determined。这对我来说似乎是一种方法(更不用说 string.length 的事实)甚至不是真实的东西并且被解释了。

长度不是一个方法,它是一个属性。除了 return 数组的长度、字符串或函数期望的参数数量之外,它实际上什么都不做。当您使用 .length 时,您只是要求 JavaScript 解释器 return 一个存储在对象中的变量;你没有调用方法。

另外,请注意 String.length 属性 给出了字符串中代码单元的实际数量,而不是文字字符数。一个编码单元是 UTF-16 定义的 16 位(JavaScript 使用)。但是,某些特殊字符使用 32 位,这意味着在包含这些字符之一的字符串中,String.length 属性 可能会为您提供比字面字符数更高的字符数。

Link:- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length

还有一个事实长度与 string.length 和 Array.length

有很大不同
let myString = "bluebells";
myString.length = 4;
console.log(myString); //bluebells
console.log(myString.length); //9


//--
let myArr = [5,6,8,2,4,7];
myArr.length = 2;
console.log(myArr); //[5, 6]
console.log(myArr.length); //2

(此处为 V8 开发人员。)

这里可以看到几个问题可以分开看:

1.从语言规范的角度来看,是方法还是 属性?

直观上,区别是:如果你写一个像obj.method()这样的函数调用,那么它就是一个方法;如果你写obj.property(没有()),那么它就是属性.

当然在JavaScript中,你也可以说一切都是属性,如果属性的当前值是一个函数,那么它就是一个方法。所以 obj.method 为您提供对该函数的引用,obj.method() 获取并立即调用它:

var obj = {};
obj.foo = function() { console.log("function called"); return 42; }
var x = obj.foo();  // A method!
var func = obj.foo;  // A property!
x = func();  // A call!
obj.foo = 42;
obj.foo();  // A TypeError!

2。当它看起来像一个 属性 访问时,它是否总是一个直接的 read/write from/to 内存,或者某些函数可能在幕后执行?

后者。 JavaScript 本身甚至为您可以创建的对象提供此功能:

var obj = {};
Object.defineProperty(obj, "property", {
  get: function() { console.log("getter was called"); return 42; },
  set: function(x) { console.log("setter was called"); }
});
// *Looks* like a pair of property accesses, but will call getter and setter:
obj.property = obj.property + 1;

关键是 obj 的用户不必关心 getters/setters 是否涉及,对他们来说 .property 看起来像 属性。这当然是非常有意的:obj 的实现细节被抽象掉了;您可以将设置 obj 及其 .property 的代码部分从普通的 属性 修改为 getter/setter 对,反之亦然,而不必担心更新其他部分read/write 它的代码。

一些内置对象依赖于此技巧,最常见的示例是数组的 .length:虽然 specified 成为具有某些“魔术”行为的 属性,引擎实现这一点的最直接方法是在引擎盖下使用 getter/setter 对,特别是 setter 会在您将长度设置为较小的值时截断任何额外的数组元素比以前.

3。那么 "abc".length 在 V8 中做了什么?

它直接从内存中读取一个属性。 V8 中的所有字符串在内部总是有一个长度字段。正如评论者指出的那样,JavaScript 字符串是不可变的,因此内部长度字段仅写入一次(在创建字符串时),然后变为只读 属性.

当然这是一个内部实现细节。假设地,引擎可以在内部使用“C 风格”字符串格式,然后在需要时它必须使用类似 strlen() 的函数来确定字符串的长度。然而,在托管堆上,能够快速确定每个对象的大小通常对性能很重要,所以如果引擎真的做出这种选择,我会感到惊讶。明确存储长度的“Pascal 风格”字符串更适合 JavaScript 和类似的垃圾收集语言。

所以,特别是,我想说,无论字符串的长度如何,读取 JavaScript 中的 myString.length 总是一个非常快速的操作是公平的,因为它 不会 迭代字符串。

4. String.length呢?

好吧,这与字符串或其长度没有任何关系:-)

String 是一个函数(例如,你可以调用 String(123) 得到 "123"),并且所有函数都有一个 length 属性 来描述它们的编号形式参数:

function two_params(a, b) { }
console.log(two_params.length);  // 2

至于这到底是“简单的 属性”还是 getter:没有理由认为它不是简单的 属性,但也没有理由假设引擎不能在内部做他们想做的事(只要没有可观察到的功能差异),如果他们认为这会提高性能或节省内存或简化事情或改进他们关心的其他一些指标:-)
(并且引擎可以并且确实利用这种自由,用于各种形式的“惰性”/按需计算、缓存、优化——有很多你可能不会想到的内部函数调用,另一方面您“清楚地看到”作为 JS 源代码中的函数调用的内容可能(或可能不会!)被内联或以其他方式优化掉。细节会随着时间的推移和不同的引擎而变化。)