Bootstrap

Ts函数作为参数传递以及作用域问题总结

  1. 箭头函数作用域

   项目中调用方法时经常用到this,而this的指向也是极易改变的,所以对于一些复杂的函数,一般会先定义

const self = this;防止this发生改变。那么先说明一下比较常见的情况:

export class Service {

    func1() {

    }

    func2() {
        let arr = [1, 2, 3];
        arr.forEach(function (element) {
            this.func1();//这里有问题!!!this已经不指向全局对象了
        });

    }
}

当然常规操作,我们会这样做:

export class Service {

    func1() {

    }

    func2() {
        const self = this;//先把this缓存一下
        let arr = [1, 2, 3];
        arr.forEach(function (element) {
            self.func1();//这样就没有问题了!
        });

    }
}

当然这不是我想说的,如果改成这样可行吗(箭头函数)?

export class Service {

    func1() {

    }

    func2() {
        let arr = [1, 2, 3];
        arr.forEach(element => {
            this.func1();//这里虽然是this,但是没有问题,这是箭头函数和普通函数的区别!
        });

    }
}

这里虽然是this,但是没有问题,这是箭头函数和普通函数的区别!

箭头函数不会自动绑定局部变量,如this,arguments,super,箭头函数内的this值继承自外围作用域。在箭头函数中调用 this 时,仅仅是沿着作用域链向上寻找,找到最近的一个 this 来使用。

  1. 函数作为参数
export class Service {
    constructor() {
        this.func3(this.func2);//func2作为参数传入
    }
    func3(func) {
        func();//直接执行可能有问题!!!
    }

    func1() {

    }

    func2() {
        let arr = [1, 2, 3];
        arr.forEach(element => {
            this.func1();//这里可能会找不到this;this为undefined(ts语言编写)
        });

    }
}

这种调用类似于:

export class Service {
    constructor() {
        this.func3(this.func2);//func2作为参数传入
    }
    func3(func) {
        //  func和funcTest一样
        let funcTest = function () { 
            let arr = [1, 2, 3];
            arr.forEach(element => {
                this.func1();//这个this也是undefined,这个在块级作用于内
            });
         }
         funcTest();
        // func();//直接执行可能有问题!!!
    }

    func1() {

    }

    func2() {
        let arr = [1, 2, 3];
        arr.forEach(element => {
            this.func1();//这里可能会找不到this;this为undefined(ts语言编写)
        });

    }
}

解决办法很简单,可以使用call()来指定this:

export class Service {
    constructor() {
        this.func3(this.func2);//func2作为参数传入
    }
    func3(func) {
        func.call(this);//这个this是func3的父级作用域,
    }

    func1() {

    }

    func2() {
        let arr = [1, 2, 3];
        arr.forEach(element => {
            this.func1();//这里this就继承了上面call中的this。
        });
    }
}
  1. 按值和按引用传递问题
export class Service {
    num = 1;
    obj = {key:1};
    constructor() {
        this.func1(this.num);
        this.func2(this.obj);
        console.log(this.num);//还是1,并没有变成2
        console.log(this.obj["key"]);//这个变成了2
    }

    func1(Param) {
        Param = 2;
    }
    func2(Param) {
        Param['key'] = 2;
    }
}

但是有个坑!!!!:

export class Service {
    obj: any;//只声明,没有初始化,undefined
    constructor() {
        this.func2(this.obj);
        console.log(this.obj["key"]);//这里就会报错,因为obj是undefined!!!!
    }


    func2(Param) {
        if (Param === undefined) {
            Param = {};//在里面进行初始化
        }
        Param['key'] = 2;
    }
}

完!

;