推荐关注
› Meteor
› JSLint - a JavaScript code quality tool
› jsFiddle
› D3.js
› WebStorm
推荐书目
› JavaScript 权威指南第 5 版
› Closure: The Definitive Guide
px920906

js 如何深拷贝一个函数?

  •  1
     
  •   px920906 · Feb 22, 2020 · 13300 views
    This topic created in 2454 days ago, the information mentioned may be changed or developed.

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

    33 replies  •  2023-04-18 20:53:32 +08:00
    sherryqueen
    sherryqueen
    Feb 22, 2020
    1
    拷贝一个函数?? 没了解过 占个座, 等楼下答复, 到时候来学习一下- -
    yuankui
    yuankui
    Feb 22, 2020
    2
    附楼问一下:如何序列化和反序列化一个函数?
    qinfensky
    qinfensky
    Feb 22, 2020 via iPhone
    3
    函数的作用域不是独立的吗?除了个 ththis 指向的坑有时候需要 bind,拷贝的意义是什么?费解
    lane1
    lane1
    Feb 22, 2020❤️1
    4
    @yuankui
    ```javascript
    const foo = x => x + 1

    eval(foo.toString())(1)
    ```
    afpro
    afpro
    Feb 22, 2020
    5
    为啥要 copy 一个函数 莫非 javascript 的函数是可变的?
    rabbbit
    rabbbit
    Feb 22, 2020
    6
    https://stackoverflow.com/questions/1833588/javascript-clone-a-function

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

    求大神解释
    otakustay
    otakustay
    Feb 22, 2020
    8
    不可能的,闭包是完全没办法克隆的
    zckevin
    zckevin
    Feb 22, 2020
    9
    1. hook javascript functions
    2. utilize/modify VM internals
    ila
    ila
    Feb 22, 2020 via Android
    10
    eval 吗
    MzM2ODkx
    MzM2ODkx
    Feb 22, 2020
    11
    笔记里的
    ```
    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
    gaobing
    Feb 22, 2020 via Android
    12
    ctrl c,ctrl v,深拷贝
    fengbjhqs
    fengbjhqs
    Feb 22, 2020
    13
    感觉写一个深拷贝的函数会比较现实,
    huanglexus
    huanglexus
    Feb 22, 2020
    14
    不知道楼主是不是听错了,如果是真的话,问这种问题的人很明显连基本的编程语言常识都不懂
    Hilong
    Hilong
    Feb 22, 2020 via Android
    15
    是不是如何实现深拷贝函数吧?
    px920906
    px920906
    OP
    Feb 22, 2020
    16
    @huanglexus 我当时问了一句“深拷贝一个函数?”,说是的。。面试官水平应该没问题的,之前也问了许多正常的问题。不过后悔没追问他这种需求的场景
    @fengbjhqs 我也是这么想的
    @rabbbit 当时还真没想这么多
    dartabe
    dartabe
    Feb 22, 2020
    17
    看了一下 好像上面的 eval(func.toString)是可以的
    rabbbit
    rabbbit
    Feb 22, 2020
    18
    面试者的原话说的是什么,直接问的如何深拷贝函数吗.
    我猜可能是想问如何继承构造函数?
    leafdream
    leafdream
    Feb 22, 2020
    19
    拷贝对象吧 拷贝个🔨的函数
    tlday
    tlday
    Feb 22, 2020
    20
    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 )。面试的话,我觉得答到这里应该足够了,正常编程中感觉很少出现这种需求。
    tlday
    tlday
    Feb 22, 2020
    21
    忽略代码最后两行,测试 js 时顺手写的
    hyy1995
    hyy1995
    Feb 22, 2020
    22
    面试玩的是真的花啊
    vasoner
    vasoner
    Feb 22, 2020
    23
    吃个瓜,我觉得应该是听错了,应该是应该让你写深拷贝而已
    lizz666
    lizz666
    Feb 22, 2020
    24
    曾经也有过这样的疑惑,倒是在网上看到过以下这种改变 this 的方式,可能面试官认为这样就算深拷贝函数了吧

    ```js
    function test1() {}
    test1.a = 1
    let test2 = test1.bind(null)
    test2.a // undefined
    ```
    tonytonychopper
    tonytonychopper
    Feb 22, 2020 via Android
    25
    不了解,但是可以看下 lodash 是怎么实现的
    7DLNU56W
    7DLNU56W
    Feb 22, 2020
    26
    利用 Function.prototype.bind 是不是可以实现呀~
    tinyhill
    tinyhill
    Feb 22, 2020
    27
    应该是问深拷贝时的函数问题吧,比如 JSON.stringify/parse 会 gg
    zhw2590582
    zhw2590582
    Feb 22, 2020
    28
    要么考查 bind 构造一个新函数,要么考查从现有函数体提取字符串再构造一个新函数
    mostkia
    mostkia
    Feb 23, 2020
    29
    把函数当作字符串来处理不知道是不是可以,funciton 不带括号是不执行的,反而会打印出内容,利用 toString()方法接住打印出来的函转为字符串,然后就可以输出了,要转为 fun,外面包一个 eval 执行。
    ```
    function uu(){
    alert('???');
    }
    var echo = uu.toString();

    console.log(echo);
    eval(echo);
    ```
    keenkiller
    keenkiller
    Feb 23, 2020
    30
    深拷贝一个函数?把代码复制一遍…
    revalue
    revalue
    Jul 23, 2020
    31
    @iMusic 为啥一个 eval 一个用的 new Function 呢?不能统一吗?
    cj97
    cj97
    Jan 22, 2021
    32
    浅复制,深复制同理
    ```
    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] })
    ```
    Tsuizen
    Tsuizen
    Apr 18, 2023
    33
    new Function('return ' + fn.toString())();
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   947 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 71ms · UTC 22:32 · PVG 06:32 · LAX 14:32 · JFK 17:32
    ♥ Do have faith in what you're doing.