js函数作用域this解析
js 函数作用域this
javascript中作用域链和this(上下文)的指向是很容易混淆的,简单的说就是: 作用域链取决于函数声明的位置,函数声明之后,从函数内部往外,一直到window,这就是它的作用域链,与函数调用位置无关; this指向函数调用时的对象,如果是独立调用,那就是指向window,与函数声明的位置无关;函数调用的方式有4种,this也就有4种指向:
独立调用:func(),函数独立调用,this指向window,; 方法调用:obj.func(),函数作为obj的一个方法(属性)调用,this指向obj; 构造函数调用:new func(),如果在一个函数前面带上 new 关键字来调用, 那么背地里将会创建一个连接到该函数的 prototype 的新对象,this指向这个新的对象; call、apply、bind调用:func.call(obj,value1,value2); func.apply(obj,[value1,value2]); func.bind(obj,value1,value2)(); func.bind(obj)(value1,value2);动态改变this的指向obj;独立调用和方法调用
全局环境中,this默认指向到window; 函数独立调用(不论这个函数在哪调用),this默认指向到window; 当函数被作为对象的方法(对象的一个属性)调用时,this指向该对象; 函数只有调用了之后才有this的概念,不然它只是代码而已,我们经常把函数传给一个变量,如果后面没加括号,就只是传了个函数,而不是执行结果;按 ctrl+c 复制代码
按 ctrl+c 复制代码
当函数被作为对象的方法调用时,可以使用this访问自己所属的对象,所以它能从对象中取值或对对象进行修改; this到对象的指向发生在调用的时候,如果函数没有被调用,则不会更改对象的变量; 通过this可取得它们所属对象的上下文的方法称为公共方法;如果想访问这个外部函数的this值,需要将this的值保存在一个变量里,内部函数就可以通过作用域链找到这个变量。
构造函数调用
如果一个函数用 new 关键字调用,那么这个函数就是构造函数,并且背地里会创建一个连接到该函数的 prototype 的新对象,this指向这个新对象;
如果构造函数没有形参,实例化的时候是可以不带()的;如 var a = func; 或者 var a = func(); 两种都可以;
同时我们在构造函数的时候有个约定(不是规范),首字母大写,以避免忘了写new关键字或者在普通函数前面加new;
new关键字的作用就是执行一个构造函数,并返回一个对象实例。使用new命令,它后面的函数的函数调用和普通函数调用就不一样了,步骤如下:
创建一个空对象,作为将要返回的对象实例; 将空对象的原型 _proto_ 指向构造函数的 prototype 属性; 将构造函数内部的this关键字指向空对象; 执行构造函数内部的代码;就是说this指向这个新对象,构造函数内所有针对this的操作,都会发生在这个新对象上;
javascript中构造函数是不需要有返回值的,可以认为构造函数和普通函数之间的区别就是:构造函数没有 return 语句,普通函数可以有 return 语句;
构造函数使用thsi关键字定义变量和方法,当 this 遇到 return 的时候,会发生指向不明(调用结果不明)的问题:
return返回的不是一个对象,this还是指向实例(新对象),调用结果也还是新对象; return返回的是一个对象,this就指向这个返回的对象,调用结果就是这个返回的对象; return返回的是null,this还是指向实例,调用结果也还是新对象;间接调用
通过call()、apply()、bind()方法把对象绑定到this上,叫做显式绑定。对于被调用的函数来说,叫做间接调用
call、apply、bind三者的第一个参数都是this要指向的对象, bind只是返回函数,还未调用,所以如果要执行还得在后面加个();call、apply是立即执行函数; 三者后面都可以带参数,call后面的参数用逗号隔开,apply后面的参数以数组的形式传入;bind则可以在指定对象的时候传参,和call一样,以逗号隔开,也可以在执行的时候传参,写到后面的括号中;func.call(obj,value1,value2); func.apply(obj,[value1,value2]); func.bind(obj,value1,value2)(); func.bind(obj)(value1,value2);严格模式下
在严格模式下,未指定环境对象而调用函数,则 this 值不会转型为 window。 除非明确把函数添加到某个对象或者调用 apply()或 call(),否则 this 值将是 undefined; 所以我们可以手动添加 window.函数(),将this指向window;<script type="text/javascript"> 'use strict' //严格模式 function a(){ console.log (this); } a();//undefined //在严格模式下,未指定环境对象而调用函数,则 this 值不会转型为 window , this 值将是 undefined。 //除非明确把函数添加到某个对象或者调用 apply()或 call()使用对象冒充。 window.a();//window //所以我们可以手动添加 window.函数(),来改变this指向window (function(){ console.log(this);//undefined })(); settimeout(function(){ console.log(this);//window },0); //settimeout是window的一个方法(属性),所以这里可以写成window.settimeout //所以不管是严格模式还是非严格模式,settimeout里的this始终指向window //但是有时候我们会发现settimeout中的this也有其他情况,这只是误导,当然如果你不确定的话,直接console.log(this)一下,分分钟解决 </script>
上一篇: Photoshop 一个逼真的玻璃灯泡
下一篇: Vue之路由解析