简体   繁体   中英

Function reassignment in JavaScript

I Have a function written in javascript which traces recursion calls of a function passed to it.

function trace(fn){
    let indent = 0

    return function tracedFunction(args){
        console.log("| ".repeat(indent)+"|--"+fn.name,args)
        indent += 1
        let value = fn(args)
        console.log("| ".repeat(indent)+"|--"+"return",value)
        indent -= 1
        return value
    }

}

function fibo(num){
    if(num==0 || num==1)
        return 1;
    return fibo(num-1)+fibo(num-2);
}


fibo = trace(fibo)
fibo(4)

This gives the following output

|--fibo 4
| |--fibo 3
| | |--fibo 2
| | | |--fibo 1
| | | | |--return 1
| | | |--fibo 0
| | | | |--return 1
| | | |--return 2
| | |--fibo 1
| | | |--return 1
| | |--return 3
| |--fibo 2
| | |--fibo 1
| | | |--return 1
| | |--fibo 0
| | | |--return 1
| | |--return 2
| |--return 5
5

My Questions are the following

  1. What is happening in the line fibo = trace(fibo) ?

    • A is it redefining the fibo function?
    • B is it creating a variable in global scope called fibo and assigning trace(fibo) to it?

    • if (A) is the case, is it a good practice to do so? Is there any other way to do this?

What you're doing here is called a "decorator". This is a very common and widely used feature in python, but in JS, after some 5 years of work, they are still in the queue. Transpilers and TypeScript do support decorators, but still it's not possible to decorate a function, only a method, so you have to wrap your fibo in a class for this to work (which looks quite silly if you ask me):

function trace(target, propertyKey, descriptor) {
    let indent = 0;
    let fn = target[propertyKey];

    descriptor.value = function tracedFunction(args){
       etc
     }
}

class Dummy {
    @trace
    static fibo(num) {
        if (num == 0 || num == 1)
            return 1;
        return Dummy.fibo(num - 1) + Dummy.fibo(num - 2);
    }
}

Dummy.fibo(4)

Typescript playground

Until the decorator syntax is standardized and properly implemented, the only way to decorate a function is how you wrote it - apply a decorator and reassign to the original name.

To answer your questions, it's both A and B -- functions are first class in javascript, so assigning a function value to a variable binds that variable to that function and the old function is lost. Function declaration syntax function foo() {...} is basically just a shortcut for var foo = function.... (up to some nasty hoisting details).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM