this指向普通函数与箭头函数callapplybindarguments

    xiaoxiao2025-01-28  46

    this指向

    ① this并不指向函数,而是指向调用它的主体对象。 ③ this指向的对象,我们称之为函数的上下文context,也叫函数的调用者 普通函数调用:通过函数名()直接调用:this指向全局对象window(注意let定义的变量不是window属性,只有window.xxx定义的才是。即let a =’aaa’; this.a是undefined)构造函数调用:函数作为构造函数,用new关键字调用时:this指向新new出的对象对象函数调用:通过对象.函数名()调用的:this指向这个对象箭头函数调用:箭头函数里面没有 this ,所以永远是上层作用域this(上下文)apply和call调用:call/apply方法第一个参数是函数体内 this 的指向函数作为数组的一个元素,通过数组下标调用的:this指向这个数组函数作为window内置函数的回调函数调用:this指向window(如setInterval setTimeout 等)

    严格模式下, this为undefined 

    console.log("通过函数名()直接调用:this指向window"); let x = 2; function test() { console.log(this); console.log(this.x); console.log(x); } test();//Object [global] console.log("通过对象.函数名()调用的:this指向这个对象"); let obj = { x : 3, objTestest: test, }; obj.objTestest(); //{ x: 3, objTestest: [Function: test] } console.log("函数作为构造函数,用new关键字调用时:this指向新new出的对象"); let newobj = new test(); //test {} console.log("函数作为数组的一个元素,通过数组下标调用的:this指向这个数组"); let arr = [1,2,test,4]; //test表示的是函数对象,即整个这个function,而test()表示调用函数,有return就对应一个返回值 arr[2](); //[ 1, 2, [Function: test], 4 ] console.log("函数作为window内置函数的回调函数调用:this指向window(如setInterval setTimeout等)"); setTimeout(test,0); //Timeout {} console.log("普通函数与箭头函数"); let obj={ a:222, fn:function(){ setTimeout(function(){console.log(this.a)}) } }; obj.fn();//undefined //this 指向是 window setTimeout,window 下面没有a ,所以这里输出 undefined。 let obj={ a:222, fn:function(){ setTimeout(()=>{console.log(this.a)}); } }; obj.fn();//222 //这次输出 222 是因为,传给 setTimeout 的是箭头函数,然后箭头函数里面没有 this ,所以要向上层作用域查找,在这个例子上, setTimeout 的上层作用域是 fn。而 fn 里面的 this 指向 obj ,所以 setTimeout 里面的箭头函数的 this ,指向 obj 。所以输出 222 console.log("call/apply"); let obj1={ a:222 }; let obj2={ a:111, fn:function(){ alert(this.a); } } // obj2.fn.call(obj1); /call 和 apply 两个主要用途就是 // 1.改变this的指向 (把 this 从 obj2 指向到 obj1 ) // 2.方法借用 (obj1 没有 fn ,只是借用 obj2 方法) 输出结果: 通过函数名()直接调用:this指向window Object [global] { ... } undefined (这个不会输出上面定义的let对象,因为他不是window,换成window.x = 2就输出2了) 2 通过对象.函数名()调用的:this指向这个对象 { x: 3, objTestest: [Function: test] } 3 2 函数作为构造函数,用new关键字调用时:this指向新new出的对象 test {} undefined 2 函数作为数组的一个元素,通过数组下标调用的:this指向这个数组 [ 1, 2, [Function: test], 4 ] undefined 2 函数作为window内置函数的回调函数调用:this指向window( setInterval setTimeout 等) Timeout { ... } undefined 2

    注意全局环境下定义的变量不是全局属性哦。如果没有定义window.namef,会输出undefined

    参考:https://blog.csdn.net/weixin_37722222/article/details/81625826 这个讲的很好

    普通函数与箭头函数

     区别:

    1.写法

    // es5     var fn = function(a, b) {         return a + b;     }     // es6 箭头函数写法,当函数直接被return时,可以省略函数体的括号     const fn = (a, b) => a + b;          // es5     var foo = function() {         var a = 20;         var b = 30;         return a + b;     }     // es6     const foo = () => {        const a = 20;        const b = 30;        return a + b;     }

    当函数参数只有一个时,括号可以省略。函数体(中括号)中有且只有一行return语句时,中括号及return 关键字可以省略。

    2.this指向

    箭头函数中没有this。如果你在箭头函数中使用了this,那么该this一定就是外层的this。

    function A() { let a = 3; this.a = 4; console.log(this); //A { a: 4 } setTimeout(function() { console.log(a) //3 },100); setTimeout(function() { console.log(this.a);//undefined this指向是Timeout{}方法 },200); setTimeout(() => { console.log(a) //3 },300); setTimeout(() => { console.log(this.a) //4 在箭头函数里面,没有 this ,箭头函数里面的 this 是继承外面的环境。 },400) } new A();

    3.构造函数

    function是可以定义构造函数的,而箭头函数是不行的。

    //使用function方法定义构造函数 function Person(name, age){ this.name = name; this.age = age; } var lenhart = new Person(lenhart, 25); console.log(lenhart); //{name: 'lenhart', age: 25} //尝试使用箭头函数 var Person = (name, age) =>{ this.name = name; this.age = age; }; var lenhart = new Person('lenhart', 25); //Uncaught TypeError: Person is not a constructor

    4.变量提升

    由于js的内存机制,function提升的级别最高,而用箭头函数定义函数的时候,需要var/ let/const关键词,变量提升只会提升变量名的声明,而不会提升变量的赋值初始化,故箭头函数一定要定义于调用之前!

    aaa(); bbb(); //报错ReferenceError: bbb is not defined function aaa() { console.log(1); } let bbb = ()=>console.log(2);

    call/apply/bind

    相同:

    三者都是用来改变函数的this对象的指向的; 三者第一个参数都是this要指向的对象,也就是想指定的上下文; 三者都可以利用后续参数传参;

    不同:

    apply和call传入的参数列表形式不同。appl接收arguments,call接收一串参数列表

    bind 主要就是将函数绑定到某个对象,bind()会创建一个函数,返回对应函数便于稍后调用;而apply、call则是立即调用。

    var obj = {     x: 81, }; var foo = {     getX: function() {         return this.x;     } }; var getX = foo .getX; getX (); // 9  因为"this"指向全局对象 console.log(foo.getX.bind(obj)());  //81(方法名后多了括号) console.log(foo.getX.call(obj));    //81 console.log(foo.getX.apply(obj));   //81

     arguments

     arguments与数组

    相同点:

    都可用下标访问每个元素都有length属性

    不同点:

    数组对象的类型是Array,类数组对象的类型是Object;类数组对象不能直接调用数组API;数组遍历可以用for in和for循环,类数组只能用for循环遍历;

    arguments 用法

    实现重载(overload):当函数的参数个数不明确时,函数体根据参数的不同进行相应处理arguments.length实现递归:在函数内部反复的调用函数本身arguments.callee(在严格模式下不允许arguments.callee) function factorial(num) {     if(num<=1) {         return 1;     }else {         return num * arguments.callee(num-1);     } }

    arguments 转数组

    Array.prototype.slice.call(arguments);

    或者  [ ].slice.call(arguments);

    Array.from() 是个非常推荐的方法,其可以将所有类数组对象转换成数组。

    arguments  参考: https://blog.csdn.net/xiaotao_css/article/details/72794650

    最新回复(0)