永利402游戏网站

当前位置:永利402游戏网站-永利402com官方网站 > 永利402游戏网站 > 浅析Javascript 中的 this 的七种使用场景

浅析Javascript 中的 this 的七种使用场景

来源:http://www.xtcsyb.com 作者:永利402游戏网站-永利402com官方网站 时间:2019-12-04 00:46

换个思路清楚Javascript中的this

2017/07/27 · JavaScript · this

初藳出处: Leechikit   

在网络海人民广播广播台大稿子都对 Javascript 中的 this 做了详细的牵线,但许多是介绍各种绑定方式或调用格局下 this 的指向,于是作者想有三个联结的笔触来越来越好驾驭 this 指向,使大家更加好推断,以下有点剧情不是原理,而是大器晚成种解题思路。

Javascript 中的 this,一时候令人吸引,所以总括了须臾间关于this指向的题目。

从call方法开头

call 方法允许切换函数推行的上下文蒙受(context),即 this 绑定的对象。

大部介绍 this 的小说中都会把 call 方法放到最终介绍,但此文我们要把 call 方法放在第4个人介绍,并从 call 方法切入来探讨 this ,因为 call 函数是显式绑定 this 的指向,大家来走访它怎样模拟达成(不考虑传入 nullundefined 和原始值):

Function.prototype.call = function(thisArg) { var context = thisArg; var arr = []; var result; context.fn = this; for (let i = 1, len = arguments.length; i < len; i++) { arr.push('arguments[' + i + ']'); } result = eval("context.fn(" + arr + ")"); delete context.fn; return result; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Function.prototype.call = function(thisArg) {
    var context = thisArg;
    var arr = [];
    var result;
 
    context.fn = this;
 
    for (let i = 1, len = arguments.length; i < len; i++) {
        arr.push('arguments[' + i + ']');
    }
 
    result = eval("context.fn(" + arr + ")");
 
    delete context.fn;
 
    return result;
}

从上述代码大家得以看来,把调用 call 方法的函数作为第七个参数对象的主意,这时约等于把第二个参数对象作为函数实践的上下文遇到,而 this 是指向函数试行的上下文景况的,由此 this 就本着了第八个参数对象,达成了 call 方法切换函数执行上下文情形的效率。

在函数中 this 到底取何值,是在函数真正被调用奉行的时候鲜明下来的,函数定义的时候明显不了。

目的方法中的this

在模拟 call 方法的时候,我们运用了对象方法来改动 this 的指向。调用对象中的方法时,会把目的作为艺术的上下文处境来调用。

既然 this 是指向实行函数的上下文情形的,那大家先来琢磨一下调用函数时的施行上下文意况。

下边笔者门来探视调用对象方法时进行上下文是哪些的:

var foo = { x : 1, getX: function(){ console.log(this.x); } } foo.getX();

1
2
3
4
5
6
7
var foo = {
    x : 1,
    getX: function(){
        console.log(this.x);
    }
}
foo.getX();

图片 1

从上航海用教室中,我们能够观望getX方法的调用者的上下文是foo,因此getX主意中的 this 指向调用者上下文foo,转换成 call 方法为foo.getX.call(foo)

上面大家把任何函数的调用情势都按调用对象方法的笔触来退换。

因为 this 的取值是函数实行上下文(context卡塔尔(英语:State of Qatar)的意气风发有些,每回调用函数,都会发生二个新的实施上下文情状。现代码中使用了 this,这几个 this 的值就径直从实践的前后文中获取了,而不会从作用域链中寻觅。

结构函数中的this

function Foo(){ this.x = 1; this.getX = function(){ console.log(this.x); } } var foo = new Foo(); foo.getX();

1
2
3
4
5
6
7
8
function Foo(){
    this.x = 1;
    this.getX = function(){
        console.log(this.x);
    }
}
var foo = new Foo();
foo.getX();

执行 new 假如不思量原型链,只考虑上下文的切换,就也就是先创造二个空的对象,然后把这么些空的对象作为构造函数的上下文,再去推行布局函数,最终回到这一个目的。

var newMethod = function(func){ var context = {}; func.call(context); return context; } function Foo(){ this.x = 1; this.getX = function(){ console.log(this.x); } } var foo = newMethod(Foo); foo.getX();

1
2
3
4
5
6
7
8
9
10
11
12
13
var newMethod = function(func){
    var context = {};
    func.call(context);
    return context;
}
function Foo(){
    this.x = 1;
    this.getX = function(){
        console.log(this.x);
    }
}
var foo = newMethod(Foo);
foo.getX();

至于 this 的取值,大要上得以分为以下二种情况:

图片 2

状态生机勃勃:全局 & 调用经常函数

DOM事件管理函数中的this

DOMElement.addEventListener('click', function(){ console.log(this); });

1
2
3
DOMElement.addEventListener('click', function(){
    console.log(this);
});

把函数绑定到DOM事件时,能够看成在DOM上加码贰个函数方法,当接触这么些事件时调用DOM上相应的事件措施。

DOMElement.clickHandle = function(){ console.log(this); } DOMElement.clickHandle();

1
2
3
4
DOMElement.clickHandle = function(){
    console.log(this);
}
DOMElement.clickHandle();

图片 3

在全局处境中,this 长久指向 window。

日常函数中的this

var x = 1; function getX(){ console.log(this.x); } getX();

1
2
3
4
5
var x = 1;
function getX(){
    console.log(this.x);
}
getX();

这种场馆下,大家创立三个假造上下文对象,然后普通函数作为那一个设想上下文对象的点子调用,当时习感觉常函数中的this就本着了那个编造上下文。

那那一个编造上下文是何等啊?在非严刻方式下是全局上下文,浏览器里是 window ,NodeJs里是 Global ;在从严形式下是 undefined

var x = 1; function getX(){ console.log(this.x); } [viturl context].getX = getX; [viturl context].getX();

1
2
3
4
5
6
7
var x = 1;
function getX(){
    console.log(this.x);
}
 
[viturl context].getX = getX;
[viturl context].getX();

图片 4

console.log(this === window);    //true

闭包中的this

var x = 1; var foo = { x: 2, y: 3, getXY: function(){ (function(){ console.log("x:" + this.x); console.log("y:" + this.y); })(); } } foo.getXY();

1
2
3
4
5
6
7
8
9
10
11
12
var x = 1;
var foo = {
    x: 2,
    y: 3,
    getXY: function(){
        (function(){
            console.log("x:" + this.x);
            console.log("y:" + this.y);
        })();
    }
}
foo.getXY();

这段代码的上下文如下图:图片 5

这里必要小心的是,大家再研究函数中的 this 指向时,只须求关爱 this 所在的函数是何等调用的, this 所在函数外的函数调用皆以浮云,是无需关怀的。由此在装有的图示中,大家只需求关爱深黑框中的内容。

故此这段代码大家关切的有的只有:

(function(){ console.log(this.x); })();

1
2
3
(function(){
    console.log(this.x);
})();

与普通函数调用同样,成立二个伪造上下文对象,然后普通函数作为这么些虚构上下文对象的方式即刻调用,佚名函数中的 this 也就针对了这一个编造上下文。图片 6

习见函数在调用时候(注意不是布局函数,前边不加 new卡塔尔国,个中的 this 也是指向 window。

参数中的this

var x = 1; var foo = { x: 2, getX: function(){ console.log(this.x); } } setTimeout(foo.getX, 1000);

1
2
3
4
5
6
7
8
var x = 1;
var foo = {
    x: 2,
    getX: function(){
        console.log(this.x);
    }
}
setTimeout(foo.getX, 1000);

函数参数是值传递的,因此地点代码等同于以下代码:

var getX = function(){ console.log(this.x); }; setTimeout(getX, 1000);

1
2
3
4
var getX = function(){
    console.log(this.x);
};
setTimeout(getX, 1000);

接下来大家又重返了家常函数调用的难题。

var x = 10;

大局中的this

大局中的 this 指向全局的上下文

var x = 1; console.log(this.x);

1
2
var x = 1;
console.log(this.x);

图片 7

function foo(){

复杂气象下的this

var x = 1; var a = { x: 2, b: function(){ return function(){ return function foo(){ console.log(this.x); } } } }; (function(){ var x = 3; a.b()()(); })();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var x = 1;
var a = {
    x: 2,
    b: function(){
        return function(){
            return function foo(){
                console.log(this.x);
            }        
        }
    }
};
 
(function(){
    var x = 3;
    a.b()()();
})();

来看上边的情形是有超级多个函数,但我们只须求关心 this 所在函数的调用形式,首先大家来简化一下之类:

var x = 1; (function(){ var x = 3; var foo = function(){ console.log(this.x); } foo(); });

1
2
3
4
5
6
7
8
var x = 1;
(function(){
    var x = 3;
    var foo = function(){
        console.log(this.x);
    }
    foo();
});

this 所在的函数 foo 是个日常函数,大家创设一个设想上下文对象,然后普通函数作为那些编造上下文对象的措施立刻调用。因而这些 this针对了这几个虚构上下文。在非严俊形式下是全局上下文,浏览器里是 window ,NodeJs里是 Global ;在严酷情势下是 undefined

console.log(this);    //Window

总结

在急需看清 this 的对准期,我们能够安装这种思路来通晓:

  • 判断 this 在大局中OLAND函数中,若在大局中则 this 指向全局,若在函数中则只关心这一个函数并三回九转决断。
  • 判断 this 所在函数是或不是作为目的方法调用,倘诺则 this 指向那些指标,不然继续操作。
  • 成立二个杜撰上下文,并把this所在函数作为这一个虚构上下文的章程,那时候 this 指向这几个编造上下文。
  • 在非严苛格局下虚构上下文是大局上下文,浏览器里是 window ,Node.js里是 Global ;在严俊情势下是 undefined

图示如下:

图片 8

 

1 赞 6 收藏 评论

图片 9

console.log(this.x);  //10

}

foo();

意况二:布局函数

所谓的结构函数正是由二个函数 new 出来的靶子,平时结构函数的函数名首字母大写,举个例子像 Object,Function,Array 这么些都归于布局函数。

function Foo(){

this.x = 10;

console.log(this);    //Foo {x:10}

}

var foo = new Foo();

console.log(foo.x);      //10

上述代码,如若函数作为结构函数使用,那么内部的 this 就表示它就要 new 出来的对象。

只是黄金时代旦一向调用 Foo 函数,而不是 new Foo(卡塔尔国,那就变成情状1,这时 Foo(卡塔尔(قطر‎就改成平时函数。

function Foo(){

this.x = 10;

console.log(this);    //Window

}

var foo = Foo();

console.log(foo.x);      //undefined

场所三:对象方法

假若函数作为对象的艺术时,方法中的 this 指向该目的。

var obj = {

x: 10,

foo: function () {

console.log(this);        //Object

console.log(this.x);      //10

}

};

obj.foo();

注意:假若在指标方法中定义函数,那么境况就分裂了。

var obj = {

x: 10,

foo: function () {

function f(){

console.log(this);      //Window

console.log(this.x);    //undefined

}

f();

}

}

obj.foo();

能够那样驾驭:函数 f 尽管是在 obj.foo 内部定义的,但它依旧归属三个平日性函数,this 仍指向 window。

在此,假若想要调用上层功能域中的变量 obj.x,能够运用 self 缓存外部this 变量。

var obj = {

x: 10,

foo: function () {

var self = this;

function f(){

console.log(self);      //{x: 10}

console.log(self.x);    //10

}

f();

}

}

obj.foo();

设若 foo 函数不作为对象方法被调用:

var obj = {

x: 10,

foo: function () {

console.log(this);      //Window

console.log(this.x);    //undefined

}

};

var fn = obj.foo;

fn();

obj.foo 被赋值给叁个全局变量,并不曾作为 obj 的壹特质量被调用,那么当时this 的值是 window。

气象四:布局函数 prototype 属性

function Foo(){

this.x = 10;

}

Foo.prototype.getX = function () {

console.log(this);        //Foo {x: 10, getX: function}

console.log(this.x);      //10

}

var foo = new Foo();

foo.getX();

在 Foo.prototype.getX 函数中,this 指向的 foo 对象。不仅如此,即就是在任何原型链中,this 代表的也是现阶段指标的值。

情况五:函数用 call、apply或者 bind 调用。

var obj = {

x: 10

}

function foo(){

console.log(this);    //{x: 10}

console.log(this.x);  //10

}

foo.call(obj);

foo.apply(obj);

foo.bind(obj)();

当三个函数被 call、apply 大概 bind 调用时,this 的值就取传入的对象的值。

情况六:DOM event this

在七个 HTML DOM 事件管理程序里,this 始终指向这几个处理程序所绑定的 HTML DOM 节点:

function Listener(){

document.getElementById('foo'卡塔尔(قطر‎.addEventListener('click', this.handleClick卡塔尔(قطر‎;    //这里的 this 指向 Listener 那些指标。不是强调的是这里的 this

}

Listener.prototype.handleClick = function (event) {

console.log(this);    //

}

var listener = new Listener();

document.getElementById('foo').click();

其大器晚成很好精晓,就约等于是给函数字传送参,使 handleClick 运转时上下文字改善变了,也正是上面那样的代码:

var obj = {

x: 10,

fn: function() {

console.log(this);        //Window

console.log(this.x);      //undefined

}

};

function foo(fn) {

fn();

}

foo(obj.fn);

您也得以用经过 bind 切换上下文:

function  Listener(){

document.getElementById('foo').addEventListener('click',this.handleClick.bind(this));

}

Listener.prototype.handleClick = function (event) {

console.log(this);    //Listener {}

}

var listener = new Listener();

document.getElementById('foo').click();

前多种情景其实能够总括为: this 指向调用该方法的对象。

气象七:箭头函数中的 this

当使用箭头函数的时候,情形就天差地别了:箭头函数内部的 this 是词法作用域,由上下文显明。

var obj = {

x: 10,

foo: function() {

var fn = () => {

return () => {

return () => {

console.log(this);      //Object {x: 10}

console.log(this.x);    //10

}

}

}

fn()()();

}

}

obj.foo();

现行反革命,箭头函数完全修复了 this 的指向,this 总是指向词法作用域,也便是外围调用者 obj。

纵然接纳箭头函数,从前的这种 hack 写法:

var self = this;

就不再须要了。

var obj = {

x: 10,

foo: function() {

var fn = () => {

return () => {

return () => {

console.log(this);    // Object {x: 10}

console.log(this.x);  //10

}

}

}

fn.bind({x: 14})()()();

fn.call({x: 14})()();

}

}

obj.foo();

出于 this 在箭头函数中早已根据词法效能域绑定了,所以,用 call(卡塔尔也许apply(卡塔尔国调用箭头函数时,不大概对 this 进行绑定,即传入的率先个参数被忽略。

本文由永利402游戏网站-永利402com官方网站发布于永利402游戏网站,转载请注明出处:浅析Javascript 中的 this 的七种使用场景

关键词:

上一篇:教你用 HTML5 制作Flappy Bird(下)

下一篇:没有了