javascript中的this词法

来源:互联网 发布:网络整合营销 编辑:程序博客网 时间:2024/06/06 12:36

this的绑定规则

this是在运行时进行绑定的,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。当一个函数被调用时,会创建一个活动记录(执行上下文),这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录其中的一个属性,会在函数执行的过程中用到。

绑定规则

1. 默认绑定
最常用的函数调用类型:独立函数调用。

function foo(){    console.log(this.a);}var a=2;foo();

this.a被解析成了全局变量a,因为函数调用应用了this的默认绑定,因此this指向全局变量。在这里,foo()直接使用了不带任何修饰符的函数引用进行调用,因此看出foo()只能使用默认绑定,无法应用其他规则。

如果使用严格模式,那么全局对象无法使用默认绑定,this会被绑定到undefined。严格模式下与foo()的调用位置无关。

2. 隐式绑定
考虑规则:调用位置是否有上下文,或者说是被某个对象包含。

function foo(){    console.log(this.a);}var obj={    a:2,    foo:foo};obj.foo();

当foo()被调用时,它的落脚点指向了obj对象。当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象,因为调用foo时this绑定到obj,因此this.a和obj.a是一样的。

    对象属性引用链中只有最顶层会影响调用位置。
function foo(){    console.log(this.a);}var obj2={    a:42;    foo:foo};var obj1={    a:2,    obj2:obj2};obj1.obj2.foo();//42
隐式丢失:一个常见的this绑定问题就是被隐式绑定的函数会丢失绑定对象,也就是说会应用默认绑定,从而把this绑定到全局对象或者undefined上,取决于是否是严格模式。
function foo(){    console.log(this.a);}var obj={    a:2,    foo:foo};var bar=obj.foo;//函数别名var a="oops,global";bar();

虽然bar是obj.foo的一个引用,但是,它引用了foo函数本身,因此此时的bar实际是一个不带任何修饰的函数调用,因此应用了默认绑定。

function foo(){    console.log(this.a);}function doFoo(fn){    fn();}var obj={    a:2,    foo:foo};var a="oops,global";doFoo(obj.foo);//oops,global

参数传递实际就是一种隐式赋值,因此我们传入函数时也会被隐式赋值。

隐式绑定时,我们必须在一个对象内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把this绑定到这个对象上。
window.id='window';document.getElementById('div').onclick=function(){    alert(this.id);//div1    var callback=function(){        alert(this.id);//window    }}
document.getElementById('div1').onclick=function(){    var that=this;    var callback=function(){        alert(that.id);//div1    }    callback();}

3. 显示绑定

 显示绑定可以解决丢失绑定的问题

1、硬绑定

function foo(){    console.log(this.a);}var obj={    a:2};var bar=function(){    foo.call(obj);};bar();//2setTimeout(bar,100);//2//硬绑定的bar不能再修改它的thisbar.call(window);//2
硬绑定的应用场景就是创建一个包裹函数,传入所有的参数并返回接收到的所有值。

2、API调用的“上下文”

function foo(el){    console.log(el,this.id);}var obj={    id:"awesome"};[1,2,3].forEach(foo,obj);

4. new绑定

使用new来调用函数,会自动执行以下操作
1、创建一个新对象
2、这个新对象会被执行原型连接
3、这个新对象会被绑定到函数调用的this
4、如果函数没有返回其他对象,那么new表达式的函数调用会自动返回这个新对象。


判断this

1、函数是否在new中调用,如果是的话this绑定的是新创建的对象
2、函数是否通过call、apply或者硬绑定调用,如果是的话,this绑定的是指定的对象
3、函数是否在某个上下文对象中调用(隐式绑定),如果是的话,this绑定的是那个上下文对象
4、如果都不是的话,使用默认绑定,严格模式下,绑定到undefined,否则绑定到全局对象。

this的四种使用场景

this要在执行时才能确认值,定义时无法确认。
var a={    name:'A',    fn:function(){        console.log(this.name)    }}a.fn() //this===aa.fn.call({name:'B'})//this==={name:'B'}var fn1=a.fnfn1()//this===window

1、作为构造函数执行

function Foo(name){    this.name=name}var f=new Foo('zhangsan')

2、作为对象属性执行

var obj={    name:'A',    printName:function(){        console.log(this.name)    }}obj.printName()

3、作为普通函数执行

function fn(){    console.log(this)}fn()

4、call apply bind

function fn1(name){    alert(name);    console.log(this)}fn1.call({x:100},'zhangsan')var fn2=function(name,age){    alert(name);    console.log(this);}.bind({y:200})fn2('zhangsan',20)
原创粉丝点击