Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

为什么primitive类型可以访问属性?

  我们在使用字符串时经常直接调用上面的内置方法,而那些内置方法是在String.prototype上才定义的。字符串本身是primitive类型,它不是String的实例,甚至都不是Object的实例。那为什么我们可以直接在字符串上调用String.prototype上的方法呢?
  我觉得很少会有人去思考这样的问题,字符串可以调用字符串相关的方法不是天经地义的嘛,有什么好奇怪的?但是我们知道primitive类型上是不能绑定属性的,而[[Prototype]]本身就是一个内置属性,它是object类型才具有的。这意味着普通的字符串甚至都没有[[Prototype]]属性,那就更别提继承了。
  这个问题的关键不是primitive类型的本质,这得从“.”(dot)说起。dot的作用是从一个object类型中取出属性引用,但如果dot运算的左操作数是primitive类型怎么办?我们可以参考其它运算符的行为,比如"2"*3这个表达式大家都知道结果吧?乘法运算符的左操作数需求一个数字类型,遇到其它类型时候就做转换。dot也具有同样的性质,只不过它的左操作数需求一个object类型,因此调用ToObject内置函数来做了类型转换。因此我们才得以从一个字符串直接访问到String.prototype上的方法。
  以上是我的解释,但在ECMAScript中,dot的概念只是一个属性访问表达式而已,它不被当成运算符。当然具体会比我描述的稍复杂些,这个转换不是dot直接的行为,因为dot运算符需要调用GetValue内置函数,到GetValue中才做了ToObject。
  但ECMAScript并不能完全作为Web开发的参考,它是引擎开发的参考。引擎的具体实现方式未必会采用ECMAScript提供的方式,比如在v8中很多时候根本没有调用ToObject,因为ToObject需要一定的性能开销。
<script>
var t,i;
t=new Date;
for(i=0;i<1E8;i++);
console.log(new Date-t);
t=new Date;
for(i=0;i<1E8;i++)"次碳酸钴".charAt(0);
console.log(new Date-t);
</script>

  或者像length这样使用广泛,还经常被放在循环里的属性所有引擎对它都有优化。
<script>
var t,i;
t=new Date;
for(i=0;i<1E8;i++);
console.log(new Date-t);
t=new Date;
for(i=0;i<1E8;i++)"次碳酸钴".length;
console.log(new Date-t);
</script>

网名:
34.203.245.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^