本篇文章给大家带来的内容是关于ecma javascript中this的深入理解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
this 实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数的调用位置(也就是函数的调用方法)。
四条规则:(你不知道的js)
1. 默认绑定
function foo() { console.log( this.a );}var a = 2;foo(); // 2
无论是否在严格模式下,在全局执行上下文中(在任何函数体外部)this 都指代全局对象。(mdn)
在严格模式下,this将保持他进入执行上下文时的值,如果 this 没有被执行上下文(execution context)定义,那它将保持为 undefined。(mdn)
function foo() { use strict; console.log( this.a );}var a = 2;foo(); // typeerror: this is undefined
2. 隐式绑定/丢失当函数作为对象里的方法被调用时,它们的 this 是调用该函数的对象,且绑定只受最靠近的成员引用的影响。(mdn)
//隐式绑定function foo() { console.log( this.a );}var obj2 = { a: 42, foo: foo};var obj1 = { a: 2, obj2: obj2};obj1.obj2.foo(); // 42
//隐式丢失function foo() { console.log( this.a );}function dofoo(fn) { // fn 其实引用的是 foo fn(); // <-- 调用位置!}var obj = { a: 2, foo: foo};var a = "oops, global"; // a 是全局对象的属性dofoo( obj.foo ); // "oops, global"
3. 显示绑定如果要想把 this 的值从一个上下文传到另一个,就要用 call 或者apply 方法。(mdn)
调用f.bind(someobject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。
var obj = { count: 0, cool: function coolfn() { if (this.count < 1) { settimeout( function timer(){ this.count++; // this 是安全的 // 因为 bind(..) console.log( "more awesome" ); }.bind( this ), 100 ); // look, bind()! } }};obj.cool(); // 更酷了。
硬绑定创建一个包裹函数,传入所有的参数并返回接收到的所有值。
硬绑定会大大降低函数的灵活性,使用硬绑定之后就无法使用隐式绑定或者显式绑定来修改 this 。
// 简单的辅助绑定函数function bind(fn, obj) { return function() { return fn.apply( obj, arguments ); };}
软绑定给默认绑定指定一个全局对象和 undefined 以外的值,那就可以实现和硬绑定相同的效果,同时保留隐式绑定或者显式绑定修改 this 的能力。
function.prototype.softbind = function(obj) { var fn = this; var curried = [].slice.call( arguments, 1 );// 捕获所有 curried 参数 var bound = function() { return fn.apply( (!this || this === (window || global))?obj : this curried.concat.apply( curried, arguments ) ); }; bound.prototype = object.create( fn.prototype ); return bound;};
4. new 绑定当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。(mdn)
使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作(你不知道的js)
创建(或者说构造)一个全新的对象。
这个新对象会被执行 [[ 原型 ]] 连接。
这个新对象会绑定到函数调用的 this 。
如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。
function foo(a) { this.a = a;}var bar = new foo(2);console.log( bar.a ); // 2
四条规则优先级
new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定函数是否在 new 中调用( new 绑定)?如果是的话 this 绑定的是新创建的对象。
var bar = new foo()
函数是否通过 call 、 apply (显式绑定)或者硬绑定调用?如果是的话, this 绑定的是指定的对象。
另外:如果绑定 null 或者 undefined ,实际应用的是默认绑定规则。
var bar = foo.call(obj2)
函数是否在某个上下文对象中调用(隐式绑定)?如果是的话, this 绑定的是那个上下文对象。
var bar = obj1.foo()
如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到 undefined ,否则绑定到全局对象。
var bar = foo()
其中:间接引用函数会应用默认绑定规则
function foo() { console.log( this.a );}var a = 2;var o = { a: 3, foo: foo };var p = { a: 4 };o.foo(); // 3(p.foo = o.foo)(); // 2
例外
1. 箭头函数
箭头函数不使用 this 的四种标准规则,而是根据外层(函数或者全局)作用域来决定 this 。
在箭头函数中,this与封闭词法上下文的this保持一致。(mdn)
箭头函数会继承外层函数调用的 this 绑定(无论 this 绑定到什么)。这其实和self = this 机制一样。
箭头函数的绑定无法被修改。
2. nodejs
settimeout(function() { console.log(this) //浏览器中:window //nodejs中:timeout实例}, 0)
其他解释
https://www.zhihu.com/questio...
func(p1, p2) 等价于
func.call(undefined, p1, p2)
obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)
如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)
例子
var number = 50; var obj = { number: 60, getnum: function () { var number = 70; return this.number; } }; alert(obj.getnum()); alert(obj.getnum.call()); alert(obj.getnum.call({number:20}));
以上就是ecma javascript中this的深入理解(附示例)的详细内容。