js 如何深拷贝一个函数?

2020-02-22 11:37:18 +08:00
 px920906

前几天一个面试中的问题,听到有点懵逼,因为从没听说过这种需求,这几天搜索了一通好像也没有明确的方案,自己能想到的是用 bind ? v 友有点子吗?

11501 次点击
所在节点    JavaScript
33 条回复
sherryqueen
2020-02-22 11:41:42 +08:00
拷贝一个函数?? 没了解过 占个座, 等楼下答复, 到时候来学习一下- -
yuankui
2020-02-22 11:48:19 +08:00
附楼问一下:如何序列化和反序列化一个函数?
qinfensky
2020-02-22 11:56:20 +08:00
函数的作用域不是独立的吗?除了个 ththis 指向的坑有时候需要 bind,拷贝的意义是什么?费解
lane1
2020-02-22 12:00:48 +08:00
@yuankui
```javascript
const foo = x => x + 1

eval(foo.toString())(1)
```
afpro
2020-02-22 12:11:48 +08:00
为啥要 copy 一个函数 莫非 javascript 的函数是可变的?
rabbbit
2020-02-22 12:13:32 +08:00
https://stackoverflow.com/questions/1833588/javascript-clone-a-function

另外,怎么算函数? 普通函数 函数表达式 箭头函数 , typeof class 也返回 function 算不算函数?
很好奇什么情况下才会需要这种功能.
dartabe
2020-02-22 12:25:25 +08:00
从函数式编程的角度来看 javascript 里面函数都尽量是纯函数 有一个就行了 其他地方都是他的引用啊

求大神解释
otakustay
2020-02-22 12:30:19 +08:00
不可能的,闭包是完全没办法克隆的
zckevin
2020-02-22 12:42:22 +08:00
1. hook javascript functions
2. utilize/modify VM internals
ila
2020-02-22 12:42:33 +08:00
eval 吗
iMusic
2020-02-22 13:33:03 +08:00
笔记里的
```
function cloneFunction(func) {
const bodyReg = /(?<={)(.|\n)+(?=})/m
const paramReg = /(?<=\().+(?=\)\s+{)/
const funcString = func.toString()
if (func.prototype) {
const param = paramReg.exec(funcString)
const body = bodyReg.exec(funcString)
if (body) {
if (param) {
const paramArr = param[0].split(',')
return new Function(...paramArr, body[0])
} else {
return new Function(body[0])
}
} else {
return null
}
} else {
return eval(funcString)
}
}
```
gaobing
2020-02-22 13:37:21 +08:00
ctrl c,ctrl v,深拷贝
fengbjhqs
2020-02-22 13:46:13 +08:00
感觉写一个深拷贝的函数会比较现实,
huanglexus
2020-02-22 13:49:20 +08:00
不知道楼主是不是听错了,如果是真的话,问这种问题的人很明显连基本的编程语言常识都不懂
Hilong
2020-02-22 13:57:51 +08:00
是不是如何实现深拷贝函数吧?
px920906
2020-02-22 14:01:48 +08:00
@huanglexus 我当时问了一句“深拷贝一个函数?”,说是的。。面试官水平应该没问题的,之前也问了许多正常的问题。不过后悔没追问他这种需求的场景
@fengbjhqs 我也是这么想的
@rabbbit 当时还真没想这么多
dartabe
2020-02-22 14:20:09 +08:00
看了一下 好像上面的 eval(func.toString)是可以的
rabbbit
2020-02-22 14:20:28 +08:00
面试者的原话说的是什么,直接问的如何深拷贝函数吗.
我猜可能是想问如何继承构造函数?
leafdream
2020-02-22 14:28:11 +08:00
拷贝对象吧 拷贝个🔨的函数
tlday
2020-02-22 14:35:37 +08:00
TL;DR:考虑这种情况:
'''
const inc = v => v+1;
inc.vector = [1,2,3]; //或者用 Object.assign/Object.defineProperty
inc.vector_add = function(num) { return this.vector.map(v => v + num) };
inc.t = 1;
inc.t.a = 3;
'''
要求拷贝 inc 函数或者拷贝 inc.vector_add 函数。



正文:
个人理解首先应该问清楚是否同样拷贝 property。
因为函数式编程语言中,函数是一等公民,本质上是个 function 对象,又因为 js 里对象的特殊性(兼具其他语言 map/dict 的特性),所以问题实际上分化成两个问题,是否需要拷贝 property。
如果不需要拷贝 property,这个函数内部有可能引用自身的某个 property,需要考虑 js 里的 this 绑定问题。考虑 ES6 以后箭头函数和普通函数的 this 绑定问题(如何判断是普通函数还是箭头函数: https://stackoverflow.com/questions/28222228/javascript-es6-test-for-arrow-function-built-in-function-regular-function),无论是哪种函数,可靠的机制都是 apply 原 function 对象为 this。(这种情况需要考虑多次拷贝以后的调用栈深度,上面 StackOverflow 里的答案有人用双下划线开头的属性 hold 了一个最原始对象解决这个问题--评论有人指出 ES6 以后可以用 Symbol 而不是双下划线这种不太可靠的 trick )
如果需要拷贝 property,那么相当于 js 里如何深拷贝一个(函数)对象 /map/dict,应该就是逐个遍历这个函数对象的属性,值引用类型的拷贝值,“引用”引用类型的同样作递归的深拷贝。同时考虑是否需要拷贝 property descriptor ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor )的问题(这里有个参考答案 https://github.com/lodash/lodash/issues/3043 )。面试的话,我觉得答到这里应该足够了,正常编程中感觉很少出现这种需求。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/646565

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX