函数的调用 以及“上下文”

发布时间 2023-07-01 12:58:33作者: oOLzYOo

函数的三种调用方式

  • 全局函数

//全局函数 this指向window 因为fn全局函数是window的一个属性
        function fn() {
            console.log(this);//window
        }
        // window.fn();
        fn();
  • 对象方法

 //对象的方法
        var p = {
            name: '张三',
            age: 15,
            sayHi() {
                console.log(this);//p对象
                console.log(this === p);//true
            }
        }
        p.sayHi();
        //将fn函数赋值给对象的sayHi
        p.sayHi = fn;
        p.sayHi();//此时执行fn中代码 this指向p
  • 构造函数

  //构造函数 new会做四件事 会将this指向new创建的对象
        function Stu(name, age) {
            this.name = name;
            this.age = age;
        }
        var s = new Stu('李四', 18);
        console.log(s);


        //普通函数 相当于window.Stu()调用  this是window 给window动态加属性
        var s1 = Stu('王五', 20);
        console.log(s1);//没有返回值 结果undefined
        console.log(name);//王五
        console.log(age);//20

总结

	this谁调用 this指向谁
	全局函数中 this指向window
	对象方法中 this指向对象
	构造函数中 this指向new创建的对象
	定时器中 this默认指向window

函数的上下文调用

  • 可以动态的修改this的指向

  • call

  • 语法 函数名.call(修改this的指向,arg1,arg2...)

function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2);//this指向window
        fn.call({ name: '张三' }, 10, 20);//修改后this指向这个对象
  • apply()

  • 语法 函数名.apply(修改this的指向,[arg1,arg2...])

  • 第二个参数是数组或伪数组 会自动遍历数组或伪数组的每一个元素给函数的形参赋值

function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2);//this指向window
        fn.apply([1, 2], [30, 40]);//修改后this指向这个数组 
  • bind()
  • 语法 函数名.bind(修改this的指向,arg1,arg2...)
  • bind()不会执行这个函数 而是会返回一个修改了this之后的新函数 然后再对这个新函数进行传参
function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2);//this指向window


        //bind与call不同的是 它不会执行这个函数 
        //而是会返回一个修改了this之后的函数
        //然后在堆返回的函数传参
        //bind一般用于回调函数中 如定时器
        var fn2 = fn.bind([2, 22, 222]);
        fn2(1, 11)


        //定时器的this默认指向window 可以用bind修改this的指向
        //匿名函数
        setTimeout(function () {
            console.log(this);
            //回调函数中修改this 此时this执行对象      
        }.bind({}), 2000);


        //表达式函数
        var test = function () {
            console.log(this);
        }
        setTimeout(test.bind([10, 20]), 1000);
  • 上下文调用模式三种语法的异同点

    • 相同点: 作用都是动态修改this的指向
    • 不同点传参方式不一样
  • 上下文调用模式三种方法 其实是属于Function构造函数的原型的 意味着js中所有的函数都能使用上下文调用修改this的指向

  • 修改的this只能是引用类型

​ 如果将this改为值类型 会自动转成基本包装类型

​ 如果将this改为undefined和null 程序不会报错 也不会修改 this依旧指向window

​ 如果没有传参 this依旧指向window

新的双冒号运算符

foo::bar;
//等同于
bar.bind(foo);

foo::bar(...arguments);
//等同于
bar.apply(foo, arguments);