采纳答案成功!
向帮助你的同学说点啥吧!感谢那些助人为乐的人
老师,
我这里看到这里了不建议使用__proto__, 请问是不是在日常开发中不会用到类似于下面的赋值呢
People.__proto__ = RootClass
谢谢
先了解下稍显深奥的原理:【原理稍显复杂,这里老师总结的说下,希望对你有帮助】
V8 引擎对于方法被调用(传入相同类型的参数)多次时 或 对象中的属性或方法多次被调用时,会使用 JIT 将函数编译成二进制代码【热编译】,以后再执行传入相同类型的参数的方法或对象中的属性或方法时,就直接执行,无需重复解释代码从而提高效率 本质上就是把代码转换成静态类型固定不变,并且生成一个类模板来记录属性或方法中各个变量的偏移量【就通过类模板来确定位置,关于类模板可以理解执行某个方法或对象属性中的属性或者方法时V8生成的一个记录某段执行代码中变量或方法的位置【偏移量】,以后在执行相同方法或访问对象中的相同方法或属性时可以直接从这个位置查找,从而提高效率。 但如果这时对象中 比如prototype原型对象空间的属性或方法被 __proto__属性给修改了,那么会导致V8引擎 所以的类模板记录下的偏移量要重新计算了,但很显然就把本来高效率执行的 固定不变的JIT编译好的静态类型重新退化成了动态类型【这就是所谓的字典模式】 并且需要再度多次执行,才会再次被 JIT 将函数编译成新的二进制代码,从而营销效率
说__proto__来修改属性影响性能,其实很容易误导大家, 因为运行时 任何数据的变化都会影响 JIT已经生成的变量的静态偏移量失效,比如方法参数类型的改变,对象属性中的值改变, 只是说__proto__它指向的是原型对象对象空间,而原型上的方法又是高频使用,所以如果我们多次使用原型空间上某个方法,比如show方法,JIT会将这个方法编译成二进制代码,固定成静态类型,并这时突然使用对象实例.__proto__修改了原型空间上的show方法的指向空间或删除了其中原型上的某个属性,刚才静态类型又退化成了动态类型。
但是我们发现 TS继承 JS继承 依然使用了 Son.__proto__=Parent 类似的写法 ,这样写也没有问题,而更多的要避免的是 对象实例变量.__proto__的使用,因为对象可以有很多,并且它修改的是高频使用的原型对象空间,也就是对象.__proto__会对静态化的”别人“ 造成影响,但 Son.__proto__=Parent 就不用担心,因为我们 Son.__proto__=Parent 目的是让Son来访问Parent类中的静态属性或静态方法,而且仅此用而已,自写自用。
非常感谢!
老师, 1. 对于V8编译有推荐的博客阅读吗 2.`类模板来记录属性或方法中各个变量的偏移量` 中 `变量的偏移量`怎么理解? 是指内存中变量位置发生的偏移吗? 3. 静态类型 和 动态类型 在JavaScript中是两个不同的空间吗? 我理解静态类型是已经编译好的二进制代码, 动态类型则是没有编译的二进制代码, 这个理解对吗
所谓偏移量就是 你当前访问的对象或数组元素距离 该对象在内存中的首地址的内存大小的计算 比如:定义一个整数数组,第一个元素内存地址为0abdef1 ,第二个元素的位置为0abdef5, ,第三个元素的位置为0abdef9, 如果需要查找第三个元素,就直接用0abdef1+8 ,那么这个8就是 第三个元素相对于首地址的偏移量 更复杂的计算偏移量还有 对象头似于Java的对象头【比如保存数组长度的内存空间,指向Class类对象的指针。。。一般前端没必要研究】
所谓静态类型是说 JIT【即时编译器】对于反复执行并且一直保持不变的代码,无需转换成字节码,会直接生成一个本地代码【也是二进制】,这个二进制是符合CPU指令集的,所以CPU能顺利执行,以后在执行相同的代码,就可以不必解释该代码,直接找到本地代码来执行。
所谓动态代码,时说每次执行的相同区域代码都有一些变化,比如通过__proto__改变了原型对象空间, 导致每次都需要转换成字节码【非cpu识别的字节码】 进行优化后,再交给解释器执行,导致效率低下
关于V8引擎,内部机制很深,建议没有编译器开发的需求,可以暂时先了解即可,博客和百度上写的差不太多,可以直接从百度了解。
答案稍显深奥
登录后可查看更多问答,登录/注册
轻松驾驭 TypeScript 高级用法, 突破前端成长瓶颈
1.2k 15
907 12
1.0k 11
946 11
698 10