Vue源码中关于拦截数组方法的困惑?
// Vue 2.0 src/core/observer/array.js;[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
.forEach(function (method) {
// cache original method
const original = arrayProto[method]
def(arrayMethods, method, function mutator() {
// avoid leaking arguments:
// http://jsperf.com/closure-with-arguments(失效)
let i = arguments.length
const args = new Array(i)
while (i--) {
args[i] = arguments[i]
}
const result = original.apply(this, args)
注释中说避免泄露参数。不明白如果不按源码中那么写,是如何有泄露参数的风险?
回答:
这里的内存泄露是说,防止新建没必要的arguments对象,来优化性能,旧的JS引擎里arguments对象和函数参数之间有链接。如果你改了arguments对象里的值,对应的函数参数也会变,但是现在的JS引擎对arguments对象已经做过优化了,直接用arguments对象不会影响性能,vue是为了保证所有环境的性能,所以不直接用arguments对象。
回答:
我觉得楼上乔治老哥的说法已经很详细了 补充一下我的见解:
首先这里的leaking arguments
指的其实是:传递arguments对象给任何方法的这一行为
那么这里注释里写了avoid避免,那么为什么要避免这一行为呢?
因为在vue2.0那个时候 JS引擎V8会跳过对leaking arguments的优化,这也将使性能相当慢
同时arguments对象是没有filter、map和forEach这样内建到数组内的方法的,
于是这种写法既能保证V8的优化,又能得到一个具有原型对象所有内建方法的完整数组对象,
现在的V8引擎是能够针对leaking arguments进行优化的
所以我们看到现在vue2.x的最新版本2.7.14里面这块的写法:
已经变成直接拿arguments对象直接给apply方法了
参考资料:
避免修改和传递arguments
给其他方法 — 影响优化-By@berkana/github
回答:
如果不按照这种方式处理参数,直接在内部函数中使用外部函数的参数,可能会导致以下问题:
闭包引用:如果内部函数 mutator 直接引用外部函数的参数,那么在闭包中会保留对这些参数的引用。这可能导致内存泄漏,因为这些参数的引用将被持续保留,即使它们在外部函数执行完后不再需要。
参数修改:如果内部函数 mutator 直接修改外部函数的参数,可能会导致意外的副作用。因为外部函数的参数是在外部调用时传递的,如果在内部函数中直接修改这些参数,可能会影响到外部函数的调用者。
通过将外部函数的参数复制到新的数组中,并在内部函数中使用这个新数组,可以避免闭包引用和参数修改的问题,确保代码的正确性和可维护性。
GPT回答的
以上是 Vue源码中关于拦截数组方法的困惑? 的全部内容, 来源链接: utcz.com/p/934595.html