Jos*_*shu 2 javascript string v8 class string-length
我想更好地了解当我找到字符串的长度时实际发生的情况。我尝试查看 W3、ECMA 和 V8 Ignition 网站,但运气不佳。
我一直读到“JavaScript 在执行方法和属性时将原始值视为对象”。但是,我似乎无法弄清楚这是如何发生的。如果我在一个原语上调用一个方法/属性,我假设它被 Ignition 解释为一个对象,那么该类是否不需要String在某个时刻调用一个函数来迭代字符串?我觉得myString.length应该被称为方法,并且String.length可以被称为属性,具体取决于找到“属性”的时间点以及如何找到它。
基本上,我不明白为什么它被吹捧为一种属性,如果它似乎不是固有的并且必须被获取/确定。对我来说,这似乎是一种方法(更不用说 string.length 了)甚至不是一个真实的东西并且被解释了。
(V8 开发人员在此。)
我在这里可以看到几个可以单独查看的问题:
1. 从语言规范的角度来看,某物是方法还是属性?
直观上,区别在于:如果你编写像这样的函数调用obj.method(),那么它是一个方法;如果你编写的是一个方法,那么它就是一个方法。如果你写obj.property(no ()),那么它就是一个属性。
当然,在 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!
Run Code Online (Sandbox Code Playgroud)
2. 当它看起来像属性访问时,它是否总是直接从内存读取/写入,或者可能会在幕后执行某些函数?
后者。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;
Run Code Online (Sandbox Code Playgroud)
关键是用户obj不必关心是否涉及 getter/setter,对他们来说.property看起来就像一个属性。这当然是非常有意的:obj抽象掉了实现细节;您可以修改设置的代码部分,obj并将其.property从普通属性更改为 getter/setter 对,反之亦然,而不必担心更新读/写它的代码的其他部分。
一些内置对象依赖于这个技巧,最常见的例子是 arrays' .length:虽然它被指定为具有某些“神奇”行为的属性,但引擎实现这一点的最直接方法是使用 getter/setter 对引擎盖,特别是如果您将长度设置为比以前更小的值,则设置器会执行截断任何额外数组元素的工作。
3. 那么V8 做了什么? "abc".length
它直接从内存中读取属性。V8 中的所有字符串内部始终有一个长度字段。正如评论者所指出的,JavaScript 字符串是不可变的,因此内部长度字段仅写入一次(创建字符串时),然后成为只读属性。
Of course this is an internal implementation detail. Hypothetically, an engine could use a "C-style" string format internally, and then it would have to use a strlen()-like function to determine a string's length when needed. However, on a managed heap, being able to quickly determine each object's size is generally important for performance, so I'd be surprised if an engine actually made this choice. "Pascal-style" strings, where the length is stored explicitly, are more suitable for JavaScript and similar garbage-collected languages.
So, in particular, I'd say it's fair to assume that reading myString.length in JavaScript is always a very fast operation regardless of the string's length, because it does not iterate the string.
4. What about String.length?
Well, this doesn't have anything to do with strings or their lengths :-)
String is a function (e.g. you can call String(123) to get "123"), and all functions have a length property describing their number of formal parameters:
function two_params(a, b) { }
console.log(two_params.length); // 2
Run Code Online (Sandbox Code Playgroud)
As for whether that's a "simple property" or a getter under the hood: there's no reason to assume that it's not a simple property, but there's also no reason to assume that engines can't internally do whatever they want (so long as there's no observable functional difference) if they think it increases performance or saves memory or simplifies things or improves some other metric they care about :-)
(And engines can and do make use of this freedom, for various forms of "lazy"/on-demand computation, caching, optimization -- there are plenty of internal function calls that you probably wouldn't expect, and on the flip side what you "clearly see" as a function call in the JS source might (or might not!) get inlined or otherwise optimized away. The details change over time, and across different engines.)
| 归档时间: |
|
| 查看次数: |
1327 次 |
| 最近记录: |