前几天一个面试中的问题,听到有点懵逼,因为从没听说过这种需求,这几天搜索了一通好像也没有明确的方案,自己能想到的是用 bind ? v 友有点子吗?
1 sherryqueen 2020-02-22 11:41:42 +08:00 拷贝一个函数?? 没了解过 占个座, 等楼下答复, 到时候来学习一下- - |
2 yuankui 2020-02-22 11:48:19 +08:00 附楼问一下:如何序列化和反序列化一个函数? |
3 qinfensky 2020-02-22 11:56:20 +08:00 via iPhone 函数的作用域不是独立的吗?除了个 ththis 指向的坑有时候需要 bind,拷贝的意义是什么?费解 |
![]() | 4 lane1 2020-02-22 12:00:48 +08:00 ![]() |
5 afpro 2020-02-22 12:11:48 +08:00 为啥要 copy 一个函数 莫非 Javascript 的函数是可变的? |
![]() | 6 rabbbit 2020-02-22 12:13:32 +08:00 https://stackoverflow.com/questions/1833588/Javascript-clone-a-function 另外,怎么算函数? 普通函数 函数表达式 箭头函数 , typeof class 也返回 function 算不算函数? 很好奇什么情况下才会需要这种功能. |
![]() | 7 dartabe 2020-02-22 12:25:25 +08:00 从函数式编程的角度来看 Javascript 里面函数都尽量是纯函数 有一个就行了 其他地方都是他的引用啊 求大神解释 |
![]() | 8 otakustay 2020-02-22 12:30:19 +08:00 不可能的,闭包是完全没办法克隆的 |
![]() | 9 zckevin 2020-02-22 12:42:22 +08:00 1. hook Javascript functions 2. utilize/modify VM internals |
10 ila 2020-02-22 12:42:33 +08:00 via Android eval 吗 |
11 MzM2ODkx 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) } } ``` |
![]() | 12 gaobing 2020-02-22 13:37:21 +08:00 via Android ctrl c,ctrl v,深拷贝 |
13 fengbjhqs 2020-02-22 13:46:13 +08:00 感觉写一个深拷贝的函数会比较现实, |
![]() | 14 huanglexus 2020-02-22 13:49:20 +08:00 不知道楼主是不是听错了,如果是真的话,问这种问题的人很明显连基本的编程语言常识都不懂 |
![]() | 15 Hilong 2020-02-22 13:57:51 +08:00 via Android 是不是如何实现深拷贝函数吧? |
![]() | 16 px920906 OP @huanglexus 我当时问了一句“深拷贝一个函数?”,说是的。。面试官水平应该没问题的,之前也问了许多正常的问题。不过后悔没追问他这种需求的场景 @fengbjhqs 我也是这么想的 @rabbbit 当时还真没想这么多 |
![]() | 17 dartabe 2020-02-22 14:20:09 +08:00 看了一下 好像上面的 eval(func.toString)是可以的 |
![]() | 18 rabbbit 2020-02-22 14:20:28 +08:00 面试者的原话说的是什么,直接问的如何深拷贝函数吗. 我猜可能是想问如何继承构造函数? |
19 leafdream 2020-02-22 14:28:11 +08:00 拷贝对象吧 拷贝个的函数 |
![]() | 20 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 )。面试的话,我觉得答到这里应该足够了,正常编程中感觉很少出现这种需求。 |
![]() | 21 tlday 2020-02-22 14:39:19 +08:00 忽略代码最后两行,测试 js 时顺手写的 |
![]() | 22 hyy1995 2020-02-22 15:59:10 +08:00 面试玩的是真的花啊 |
![]() | 23 vasoner 2020-02-22 16:13:52 +08:00 吃个瓜,我觉得应该是听错了,应该是应该让你写深拷贝而已 |
![]() | 24 lizz666 2020-02-22 16:15:43 +08:00 曾经也有过这样的疑惑,倒是在网上看到过以下这种改变 this 的方式,可能面试官认为这样就算深拷贝函数了吧 ```js function test1() {} test1.a = 1 let test2 = test1.bind(null) test2.a // undefined ``` |
![]() | 25 tonytonychopper 2020-02-22 17:35:42 +08:00 via Android 不了解,但是可以看下 lodash 是怎么实现的 |
26 7DLNU56W 2020-02-22 18:11:40 +08:00 利用 Function.prototype.bind 是不是可以实现呀~ |
![]() | 27 tinyhill 2020-02-22 18:18:36 +08:00 应该是问深拷贝时的函数问题吧,比如 JSON.stringify/parse 会 gg |
![]() | 28 zhw2590582 2020-02-22 20:16:52 +08:00 要么考查 bind 构造一个新函数,要么考查从现有函数体提取字符串再构造一个新函数 |
![]() | 29 mostkia 2020-02-23 09:22:23 +08:00 把函数当作字符串来处理不知道是不是可以,funciton 不带括号是不执行的,反而会打印出内容,利用 toString()方法接住打印出来的函转为字符串,然后就可以输出了,要转为 fun,外面包一个 eval 执行。 ``` function uu(){ alert('???'); } var echo = uu.toString(); console.log(echo); eval(echo); ``` |
30 tairan2006 2020-02-23 20:59:49 +08:00 深拷贝一个函数?把代码复制一遍… |
32 cj97 2021-01-22 09:50:37 +08:00 浅复制,深复制同理 ``` const fn = () => 1; fn.a = 2; fn.f = () => 3; const obj = Object.assign({}, fn); const clOneFn= fn.bind(); Object.keys(obj).forEach(key => { cloneFn[key] = obj[key] }) ``` |
33 Tsuizen 2023-04-18 20:53:32 +08:00 new Function('return ' + fn.toString())(); |