严格模式下, 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 constructor4.变量提升
由于js的内存机制,function提升的级别最高,而用箭头函数定义函数的时候,需要var/ let/const关键词,变量提升只会提升变量名的声明,而不会提升变量的赋值初始化,故箭头函数一定要定义于调用之前!
aaa(); bbb(); //报错ReferenceError: bbb is not defined function aaa() { console.log(1); } let bbb = ()=>console.log(2);相同:
三者都是用来改变函数的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)); //81arguments与数组
相同点:
都可用下标访问每个元素都有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