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里面这块的写法:
Vue源码中关于拦截数组方法的困惑?
已经变成直接拿arguments对象直接给apply方法了

参考资料:
避免修改和传递arguments给其他方法 — 影响优化-By@berkana/github


回答:

如果不按照这种方式处理参数,直接在内部函数中使用外部函数的参数,可能会导致以下问题:

闭包引用:如果内部函数 mutator 直接引用外部函数的参数,那么在闭包中会保留对这些参数的引用。这可能导致内存泄漏,因为这些参数的引用将被持续保留,即使它们在外部函数执行完后不再需要。

参数修改:如果内部函数 mutator 直接修改外部函数的参数,可能会导致意外的副作用。因为外部函数的参数是在外部调用时传递的,如果在内部函数中直接修改这些参数,可能会影响到外部函数的调用者。

通过将外部函数的参数复制到新的数组中,并在内部函数中使用这个新数组,可以避免闭包引用和参数修改的问题,确保代码的正确性和可维护性。
GPT回答的

以上是 Vue源码中关于拦截数组方法的困惑? 的全部内容, 来源链接: utcz.com/p/934595.html

回到顶部