在函数中this到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了。因为this的取值是执行上下文环境的一部分。每次调用函数,都会产生一个新的执行上下文环境。
this的指向
1、构造函数
//1、 构造函数时,this指的是的 即将new出来的对象。(在构造函数的prototype,甚至在整个原型链中,this代表的都是当前对象的值。)var name = "hahaha";function Foo() {this.name = "lishuge";this.year = 1997;console.log(this); //Foo {name: "lishuge", year: 1997}}var a = new Foo();console.log(a)//Foo {name: "lishuge", year: 1997}Foo(); //Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}//直接调用函数就是window/* ------------------------------------------- */Foo.prototype.getName=function(){console.log(this.name);}var f1=new Fn();f1.getName(); //lishuge
2、函数作为对象的一个属性
//2、函数作为对象的一个属性。结果this就是obj对象。var f1 = {x: 10,f2: function () {console.log(this), //{x: 10, f2: ƒ}//2. Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}console.log(this.x) //10 //2. undefined}}f1.f2();//调用语句/* ---------------------*/// 如果fn函数被赋值到了另一个变量中,并没有作为obj的一个属性被调用,那么this的值就是window,// this.x为undefined。var a = f1.f2;a()
3、函数被call 或者apply调用时。
//当一个函数被call和apply调用时,this的调用值就取传入的对象。var obj={x=10;}var fn=function (){console.log(this); //object {x:10}console.log(this.x); //10}fn.call(obj)
4、全局 和调用普通函数
//在全局作用下,this永远是window。console.log(this==window) //true//普通函数在调用时,其中的this也都是windowvar x=10;var fn=function (){console.log(this) //Windowconsole.log(this.x) //10}fn()
改变this指向的方法
call语法:function.call(thisArg,arg1,arg2,...);apply语法:function.apply(thisArg, [ ]);bind语法:function.bind(thisArg[,arg1[,arg2[,...]]]) { function.bind(fun(param)) }
1.bind
改变了函数内部this执行的上下文环境
var name="wang"; //全局变量 是window下的属性var obj={name:"li"}var test=function(){console.log(this.name) //this指向了obj 输出结果为li}.bind(obj);test()如果不使用bind()/*var test=function(){console.log(this.name) //test是window下的方法 实际是window.name 输出wang}test()*/
2.call
改变了函数this的指向,函数调用的时候执行
<script>/* call改变函数this的指向,函数调用的时候执行*/var name="wang";var obj={name:"li"}var test=function(){console.log(this.name) //li}test.call(obj)</script>
2.1call(thisObj,parmas)的两个传参
call(thisObj,params)//第一个参数指向函数内部的this,之后的参数是需要被传入函数的参数
<script>/* call(thisObj改变this对象,params传递的参数) */function sayName(label){console.log(label+":"+this.name)}var name="zhang";var cheng={name:"cheng"}var wang={name:"wang"}sayName("window") //window:zhangsayName.call(cheng,"男孩子") //男孩子:chengsayName.call(wang,"女孩子") //女孩子:wang</script>
3.apply
fun.apply(thisArg, [argsArray])传递的是数组
<script>function go(name,age){console.log(this.name+":"+this.age)// console.log(name)// console.log(age)}go("cheng",18) //undefinedvar li={name:"李晓",age:23}var zhang={name:"张晓",age:23}go.apply(li,["li",24]) //李晓:23go.call(zhang,"zhang",111) //张晓:23</script>
三者的区别?
call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数;
call,apply的区别:
- 他们俩之间的差别在于参数的区别,call和apply的第一个参数都是要改变上下文的对象,
- 而call从第二个参数开始以参数列表的形式展现,
- apply则是把除了改变上下文对象的参数放在一个数组里面作为它的第二个参数
