Step-By-Step icon indicating copy to clipboard operation
Step-By-Step copied to clipboard

如何正确判断this的指向?(注意区分严格模式和非严格模式)

Open YvetteLau opened this issue 5 years ago • 68 comments

YvetteLau avatar May 20 '19 00:05 YvetteLau

console.log(this)

simplast avatar May 20 '19 00:05 simplast

console.log(this)

不使用 console alert 等的情况下~ 你可以当成这个问题,是你面试一家你非常想去的企业时,面试官问你的~

YvetteLau avatar May 20 '19 00:05 YvetteLau

如何判断this 指向 就需要找到这个函数的直接调用位置 找位置之后再确定this指向 1.new 调用 直接指向new 创建的新对象 2.上下文调用 直接指定上下文 3.call .apply 指向指定的 绑定对象 4.全局函数下 指向全局 es6的箭头函数 指向外层函数的this

zhangxianhui avatar May 20 '19 01:05 zhangxianhui

默认情况下 严格模式绑定到undefined,非严格模式 绑定全局上

zhangxianhui avatar May 20 '19 01:05 zhangxianhui

this指的是当前执行环境的上下文,非严格模式的全局对象绑定在window上面,在严格模式下,全局对象将无法使用默认绑定,因此this会绑定到undefined

88flyfish avatar May 20 '19 01:05 88flyfish

谁调用,this就指向谁;在严格模式下,this指向的是undeined,在非严格模式下this指向的是全局变量,通过一些特殊的方式可动态改变this,apply,call;而bind是让this再创建时就让他固定;箭头函数也可以改变this,指向的是当前全局变量

shenanheng avatar May 20 '19 01:05 shenanheng

首先this并不会指向函数本身。 1,当函数在没有任何修饰的情况下调用,非严格模式下,this指向window,严格模式下this指向undefined。(默认绑定) 2,当函数由一个对象引导调用时,this指向该对象。(隐式绑定) 3,函数通过apply,call,bind绑定时,this指向绑定的对象。(显式绑定) 4,当函数被当做构造函数使用,又new引导调用时,this只想new创建出来的对象。(new绑定); 其优先级为:new绑定 > 显示绑定 > 隐式绑定 > 默认绑定; 箭头函数其this取决于函数定义时所在的上下文。

chang229 avatar May 20 '19 01:05 chang229

非严格模式 1、存粹的函数调用,this指向window。 2、作为对象属性调用,this指向该对象。 3、call、apply时,this指向该第一个入参,如果是null,undefined,则指向window。 4、作为构造函数,this指向返回的新对象。 严格模式 1、函数内部的this指向 undefined。 2、箭头函数的this,同上一级的函数的this

jizx avatar May 20 '19 01:05 jizx

非严格模式 (1)作为对象方法的调用,this 指向该对象 (2)call .apply 指向指定的 绑定对象 (3)函数调用this指向window (4)call .apply 的this指向绑定对象 (5)箭头函数的this,指向当前的外层函数 严格模式 (1)this指向的是 undefined

dashengzi66 avatar May 20 '19 01:05 dashengzi66

非严格模式下
1.全局的this指向window 2. 函数中的this指向函数调用时所处的位置 3. 箭头函数无this指向 指向声明 4. 对象中的this,指向该对象 可以通过 new操作符 call,aplay等方式改变this指向

chongyangwang avatar May 20 '19 01:05 chongyangwang

总得来说:

this指向执行主体

分几种情况:

  1. 普通函数执行时,如果没有执行主体,在非严格模式下指向window,在严格模式下指向undefined。
  2. 箭头函数没有this,它继承上下文的this。
  3. 构造函数里的this指向生成的实例对象。
  4. 事件绑定函数中的this指向当前操作的元素。
  5. call, apply, bind把函数中的this改为指定的执行对象。

xyfay536475008 avatar May 20 '19 02:05 xyfay536475008

  • (new 绑定)当函数使用new 调用的时候,指向新创建的这个对象
  • (显示绑定)当使用call, apply时候传入的第一个参数作为this的指向,但如果传入的参数是null,就应用默认绑定规则;如果使用bind, 返回的新函数的this指向传入bind的第一个参数
  • (隐式绑定)当函数作为另一个对象的方法来调用的时候,this就指向这个对象; 这种情况下要留意绑定丢失,当把一个对象的方法作为值赋值给另一个变量或者作为参数进行传递时,就会发生绑定丢失,从而应用默认绑定规则;如果通过多个object来链式调用这个函数,以最后一个obj为准,比如a.b.fn(); fn的this指向的是b
  • (默认绑定)函数单独调用,如果函数运行在严格模式下this就绑定到undefined,非严格模式下就绑定到window对象。注意这里的严格模式是指函数内部,而不是函数上层作用域
function test(){
   'use strict' //内部
   console.log(this) // undefined
}
  • 箭头函数没有自己的this, 箭头函数的this继承了上层函数的this指向

AILINGANGEL avatar May 20 '19 02:05 AILINGANGEL

谁调用的this,this就指向谁, 1.在函数体中,简单调用该函数时(非显示/隐士绑定下),严格模式下this绑定到undefined,否则绑定到全局对象window/global; 2.一般构造函数new调用,绑定到新创建的对象上; 3.一般call,applly,bind方法显示调用,绑定到指定参数的对象上; 4.箭头函数中,根据外层上下文绑定的this决定this指向。

Liruimin2 avatar May 20 '19 02:05 Liruimin2

如何正确判断this的指向?

一、严格模式( "use strict";)

(一) 作为obj对象时

this指向obj

(二)作为function时

this指向undefined

(三)使用apply、call、bind调用

this指向绑定对象的第一个参数

(四)箭头函数

this指向上一层函数

二、非严格模式

(一) 作为obj对象时,this指向obj

image

(二)作为function时

this指向function对象

(三)使用apply、call、bind调用

this指向目标函数,null和undefined,指向全局对象(浏览器中是window),其余值指向被new Object()包装的对象

(四)使用构造函数调用

this指向new生成的新对象

参考文章

[【面试官问:JS的this指向】](https://juejin.im/post/5c0c87b35188252e8966c78a#heading-4)

青成:我的回答有不对的地方,麻烦务必指出来,我及时改正,谢谢~

luohong123 avatar May 20 '19 02:05 luohong123

对于JS代码中没有写执行主体的情况下,非严格模式默认都是window执行的,所以this指向的是window,但是在严格模式下,没有写执行主体,this指向是undefined

taoyaoyaoa avatar May 20 '19 02:05 taoyaoyaoa

MDN this

freeshineit avatar May 20 '19 02:05 freeshineit

首页一条原则是JS中的this代表的是当前行为执行的主体 1.独立函数调用,严格模式下this指向undefined,非严格模式下this指向window 2.构造函数中this指向实例 3.call、apply、bind显示绑定的this指向第一个参数。非严格模式下call的第一个参数不传或者是传入null、undefined时this指向window;严格模式下不传或者传入undefined this指向undefined,传入null时this指向null 4.箭头函数没有this,它是继承外层代码块的this,箭头函数的this不是调用时决定的,是由定义时决定的,换句话说就是:外层代码块有this,外层代码的this就是箭头函数的this,外层代码没有this,箭头函数的this就是window

wanglinyj avatar May 20 '19 02:05 wanglinyj

学习了 感谢

------------------ 原始邮件 ------------------ 发件人: "wanglinyj"[email protected]; 发送时间: 2019年5月20日(星期一) 上午10:44 收件人: "YvetteLau/Step-By-Step"[email protected]; 抄送: "爱到最美是陪伴💏"[email protected]; "Comment"[email protected]; 主题: Re: [YvetteLau/Step-By-Step] 如何正确判断this的指向?(注意区分严格模式和非严格模式) (#1)

首页一条原则是JS中的this代表的是当前行为执行的主题 1.独立函数调用,严格模式下this指向undefined,非严格模式下this指向window 2.构造函数中this指向实例 3.call、apply、bind显示绑定的this指向第一个参数。非严格模式下call的第一个参数不传或者是传入null、undefined时this指向window;严格模式下不传或者传入undefined this指向undefined,传入null时this指向null 4.箭头函数没有this,它是继承外层代码块的this,箭头函数的this不是调用时决定的,是由定义时决定的,换句话说就是:外层代码块有this,外层代码的this就是箭头函数的this,外层代码没有this,箭头函数的this就是window

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

taoyaoyaoa avatar May 20 '19 02:05 taoyaoyaoa

单独函数

function foo(){
	//'use strict'
	this.name = 'foo';
	console.log(this);
}
//1-a:直接调用
foo()//this->window   严格模式下:this->undefined 此处报错
//1-b:构造函数调用
var f = new foo();//this ->f对象
//1-c: call,apply
var obj = {name:'obj',xxx:'this is a test!'}
var f1 = foo.call(obj);//this->obj
var f2 = foo.apply(obj);//this->obj
//1-d bind
var bindObj = {name:'bindObj'}
var f3 = foo.bind(bindObj);
f3();//this->bindObj

对象方法中的this

var person = {
	name:'zhangsan',
	sayName:function(){
		console.log(this);
		return this.name;
	}
}
//2-a:通过 对象.方法的形式调用 this 指向调用的对象
person.sayName();// this->person
//2-b:外层变量对对象下方法的引用
var s = person.sayName;
//这时候  s 就回到我们之前说的情况1:单独函数 一样了

//无论函数是以对象方法存在还是 单独函数形式存在  我们拿到该函数的指针变量s 无论在哪里单独调用s()
//此时函数内部的 this 严格模式指向 undefined   非严格模式指向 window
//比如:
//
function bar(){
	s();//s函数内部this->window(严格模式 undefined)
}



domObj.addEventListener('click',function(){
	console.log(this);
	s();//s函数内部this->window(严格模式 undefined)
});
//这里 对dom元素设置监听事件 回调函数内部的this 指向  该dom对象
//下面的例子 更直观 跟2:对象方法中的this 调用  对象.方法名 类似
domObj.onclick = function(){
	console.log(this);
}

箭头函数

箭头函数内部不存在自己的this  ,这个this 只是定义该函数是所在的对象,而不是使用时所指的对象
var arrow = ()=>{console.log(this)}
arrow();//this->window

var person = {
	name:'zhangsan',
	sayName:function(){
		console.log(this);
		arrow();//arrow函数内部this->window
		var a1 = ()=>{console.log(this)}
		a1();//a1中this 指向  person(定义时所在的对象)
		return this.name;
	}
}
person.sayName();

目前想到的就这些场景

wubetter avatar May 20 '19 02:05 wubetter

谢谢 学习了 写的非常详细 我会好好看好好学习一下的

------------------ 原始邮件 ------------------ 发件人: "wubetter"[email protected]; 发送时间: 2019年5月20日(星期一) 上午10:54 收件人: "YvetteLau/Step-By-Step"[email protected]; 抄送: "爱到最美是陪伴💏"[email protected]; "Comment"[email protected]; 主题: Re: [YvetteLau/Step-By-Step] 如何正确判断this的指向?(注意区分严格模式和非严格模式) (#1)

单独函数 function foo(){ //'use strict' this.name = 'foo'; console.log(this); } //1-a:直接调用 foo()//this->window 严格模式下:this->undefined 此处报错 //1-b:构造函数调用 var f = new foo();//this ->f对象 //1-c: call,apply var obj = {name:'obj',xxx:'this is a test!'} var f1 = foo.call(obj);//this->obj var f2 = foo.apply(obj);//this->obj //1-d bind var bindObj = {name:'bindObj'} var f3 = foo.bind(bindObj); f3();//this->bindObj

对象方法中的this var person = { name:'zhangsan', sayName:function(){ console.log(this); return this.name; } } //2-a:通过 对象.方法的形式调用 this 指向调用的对象 person.sayName();// this->person //2-b:外层变量对对象下方法的引用 var s = person.sayName; //这时候 s 就回到我们之前说的情况1:单独函数 一样了 //无论函数是以对象方法存在还是 单独函数形式存在 我们拿到该函数的指针变量s 无论在哪里单独调用s() //此时函数内部的 this 严格模式指向 undefined 非严格模式指向 window //比如: // function bar(){ s();//s函数内部this->window(严格模式 undefined) } domObj.addEventListener('click',function(){ console.log(this); s();//s函数内部this->window(严格模式 undefined) }); //这里 对dom元素设置监听事件 回调函数内部的this 指向 该dom对象 //下面的例子 更直观 跟2:对象方法中的this 调用 对象.方法名 类似 domObj.onclick = function(){ console.log(this); }

箭头函数 箭头函数内部不存在自己的this ,这个this 只是定义该函数是所在的对象,而不是使用时所指的对象 var arrow = ()=>{console.log(this)} arrow();//this->window var person = { name:'zhangsan', sayName:function(){ console.log(this); arrow();//arrow函数内部this->window var a1 = ()=>{console.log(this)} a1();//a1中this 指向 person(定义时所在的对象) return this.name; } } person.sayName();

目前想到的就这些场景

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

taoyaoyaoa avatar May 20 '19 02:05 taoyaoyaoa

全局环境

无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。

函数(运行内)环境

  1. 简单调用(此调用未设置this) 非严格模式下,this 的值默认指向全局对象。 在严格模式下,this将保持他进入执行环境时的值。如果 this 没有被执行环境(execution context)定义,那它将保持为 undefined。 当一个函数在其主体中使用 this 关键字时,可以通过使用函数继承自Function.prototype 的 call 或 apply 方法将 this 值绑定到调用中的特定对象。(如果传递给 this 的值不是一个对象,JavaScript 会尝试使用内部 ToObject 操作将其转换为对象。)
  2. bind方法 ES5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论此函数是如何被调用的。
  3. 箭头函数 在箭头函数中,this与封闭词法环境的this保持一致。在全局代码中,它将被设置为全局对象。
  4. 作为对象的方法 当函数作为对象里的方法被调用时,它们的 this 是调用该函数的对象。(此概念适用于原型链中的this和getter 与 setter 中的 this)
  5. 作为构造函数 当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。(手动返回其他对象时,则绑定到返回的这个对象上)
  6. 作为一个DOM事件处理函数 当函数被用作事件处理函数时,它的this指向触发事件的元素(一些浏览器在使用非addEventListener的函数动态添加监听函数时不遵守这个约定)。
  7. 作为一个内联事件处理函数 当代码被内联on-event 处理函数调用时,它的this指向监听器所在的DOM元素。

this - JavaScript | MDN

lqzo avatar May 20 '19 03:05 lqzo

1、如何正确判断this的指向?(注意区分严格模式和非严格模式) 自己想到的: 非严格模式:this 没有上下文的时候 指向 window ,有上下文的时候this在上下文指向该函数; 严格模式:this 指向 undefined 有上下文根据不同的上下文来判断this的指向; 谁调用他就指向他 函数,api的指向问题 new bind apply,call 的指向 箭头函数没有this的、 搜索得到的 eg: function foo(){ console.log(this.a) } var a=0; foo();

const obj={
	a:1,
	foo:foo
}
obj.foo()
const c=new foo()

对于直接调用 foo 来说,不管 foo 函数被放在了什么地方,this 一定是 window 对于 obj.foo() 来说,我们只需要记住,谁调用了函数,谁就是 this,所以在这个场景下 foo 函数中的 this 就是 obj 对象 对于 new 的方式来说,this 被永远绑定在了 c 上面,不会被任何方式改变 this

对于箭头函数中的this function a() { return () => { return () => { console.log(this) } } } console.log(a()()()) 首先箭头函数其实是没有 this 的,箭头函数中的 this 只取决包裹箭头函数的第一个普通函数的 this。在这个例子中,因为包裹箭头函数的第一个普通函数是 a,所以此时的 this 是 window。另外对箭头函数使用 bind 这类函数是无效的。

bind,不知道大家是否考虑过,如果对一个函数进行多次 bind,那么上下文会是什么呢?

let a = {} let fn = function () { console.log(this) } fn.bind().bind(a)() // => ?

函数转换下

// fn.bind().bind(a) 等于 let fn2 = function fn1() { return function() { return fn.apply() }.apply(a) } fn2()

bind多次绑定 输出的值任然是 fu 中的this永远是第一次bind决定的。所以结果是 window

let datas={name:'hello'} function foo(){ console.log(this.name) } foo.bind(datas)() 如果多个规则多次出现。那么该应怎么判断this ?

首先,new 的方式优先级最高,接下来是 bind 这些函数,然后是 obj.foo() 这种调用方式,最后是 foo 这种调用方式,同时,箭头函数的 this 一旦被绑定,就不会再被任何方式所改变。

-----搜索的看的某大佬的小册, ---你好,不对的还请指教

darlingyz avatar May 20 '19 03:05 darlingyz

在严格模式下,this指向是undefined;在非严格模式下,一是直接调用时,thi指向的是全局对象;二是方法调用时,this指向的是该方法的对象;三是new调用时,this指向新的对象;四是箭头函数中,this指向方法调用的对象。 但使用bind时,this指向了绑定的对象。apply和call时,this指向第一个参数

0uzu0 avatar May 20 '19 03:05 0uzu0

this

**非严格模式** this指向全局对象 window this永远指向最后调用的那个对象

也可以使用apply、call、bind改变 this 的指向 可以参考 https://juejin.im/post/59bfe84351882531b730bac2#heading-4

wangxinyu123 avatar May 20 '19 06:05 wangxinyu123

补充加深理解 可执行代码分为三种:全局代码,evel中的代码,函数中的代码; 跟我们关系最密切的自然是函数代码的执行,尤其是作为回调函数。This从何而来呢?我们慢慢分析。 当控制流进入到一个函数内时需要创建一个环境用以执行代码,我们称之为执行上下文(不同于上下文),执行上下文包含词法环境、变量环境和this。前两项可以看为同一个标识符环境,仅在少有的情况会产生差异。根据ES5.1 10.4.3文档中的描述在严格模式下将直接指向thisArg;非严格模式下有如下判断:

1.如果为null或undefined,this指向window; 2.否则对thisArg进行类型检测,不是object类型时this指向toObject(thisArg)的返回值; 3.否则this指向thisArg。

用伪代码来演示如下:

if(hasStrict){ this = thisArg; }else if(thisArg === null || thisArg === undefined){ this = window; }else if(type(thisArg) !== object){ this = toObject(thisArg); }else{ this = thisArg; } (这里的thisArg是什么将在下文叙述,暂时可理解为call方法中传递的第一个参数)

一.正常的函数调用(默认绑定); 二.作为对象属性的函数调用(隐式绑定); 三.利用函数自身的方法调用,apply,call和bind(显式绑定); 四.new操作符调用

具体请看相关参考文章链接 参考: https://www.jianshu.com/p/93cbe502cd7a

0xBrooke avatar May 20 '19 06:05 0xBrooke

非严格模式下:函数中this调用:this-----》window

方法中this调用:this-----》当前对象(嗲用方法的对象)

构造函数中this调用:this------》该构造函数的实例对象

借用方法调用:改变this的指向

分析this的问题,需要明白两点:

  1.分析this是属于哪个函数

  2.分析该函数是以什么模式被调用的 只看函数是怎么被调用的,不管函数是怎么来的

严格模式中,函数调用模式内部的this为:undefined

Diamondjcx avatar May 20 '19 06:05 Diamondjcx

1、全局作用域中的this ES5,ES6 不管是在严格模式还是非严格模式下的this都指向 window 2、全局作用域中函数中的this ES5:严格模式this指向undefined;非严格模式this指向window ES6:严格模式或非严格模式,箭头函数的this都指向window 3、对象的属性(函数中)的this ES5:严格模式或非严格模式,this的指向都是调用这个函数的对象, ES6:严格模式或非严格模式,this的指向是执行该对象所处的执行上下文(执行环境) 4、构造函数中的this 严格模式或非严格模式,构造函数中的this指向构造函数创建的对象实例。 5、事件处理函数中的this 严格模式或非严格模式,在事件处理函数中,this指向触发事件的目标对象。

zhmfe avatar May 20 '19 06:05 zhmfe

如何判断this?(包括讨论在严格模式和非严格模式)

先不讨论严格模式和非严格模式,注意'use strict'要要么放在文件开头,要么放在函数内部,否则不起作用

JavaScript高级程序设计中有下面这一句话:

在严格模式下,未指定环境对象而调用函数,则 this 值不会转型为 window。 除非明确把函数添加到某个对象或者调用 apply()或 call(),否则 this 值将是 undefined。

this的判断我认为一般来说有几种情况:

1、普通函数调用,则this一般指向window(node下为 global )

// 严格模式
'use strict'
function outer() {
    function inner() {
        console.log(this)  // 
    }
    inner()
}
outer()
// 非严格模式 输出 global对象或者window对象(node和browser)
// 严格模式 输出 undefined

2、对象方法中调用,则this指向这个对象

var obj={
    'name':'yy',
    'age':'18',
    'val':function(){
        'use strict'   // 严格模式和非严格模式下都是指向obj这个对象
        return this;
    }
}
console.log(obj.val()) // { name: 'yy', age: '18', val: [Function: val] }

3、箭头函数调用 箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象)

var obj={
    'name':'yy',
    'age':'18',
    'val': () => {
        console.log(this)
    },
    'other': function() {
        return () => {
            console.log(this)
        }
    }
}
obj.val() // {}  返回一个空对象
obj.other()() // { name: 'yy',age: '18',val: [Function: val],other: [Function: other] }  这是由于外部函数的this指向对应的对象

4、在异步环境或者定时器环境下,this不指向原来的环境,而是函数执行时的外层函数

严格模式下:

var obj={
    'name':'yy',
    'age':'18',
    'val': () => {
        console.log(this)
    },
    'other': function() {
        'use strict'
        setTimeout( () => {
            console.log(this)
        },0)
    },
    'another': function() {
        'use strict'
        setTimeout(function(){
            console.log(this)
        },0)
    }
}
obj.other() // obj 对象
obj.another() // 在node环境下无论是不是严格模式都返回一个Timeout对象!神奇吧!在browser下是window对象

5、当函数被重新赋值时.在严格模式下,如果是箭头函数的话,this会被赋值为箭头函数外部函数对应的那个this对象,而普通函数的话,则仍然是undefined

var obj={
    'name':'yy',
    'age':'18',
    'val': () => {
        return this;
    },
    'other': function() {
        'use strict'
        return () => {      
            console.log(this)
        }
    }
    'another': function() {
        'use strict'
        return function() {       
            console.log(this)
        }
    }
}
var fn2 = obj.other() 
fn2() // 返回obj 对象,箭头函数使得this绑定到‘other'方法对应的this对象
var fn3 = obj.another()
fn3() // undefined

6、call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象

var obj={
    'name':'yy',
    'age':'18',
    'val': function() {
        console.log(this)
    }
}
obj.val()    // { name: 'yy', age: '18', val: [Function: val] }
var fn = obj.val;
fn();  // 全局对象
fn.call(obj) // { name: 'yy', age: '18', val: [Function: val] }

toyxz avatar May 20 '19 07:05 toyxz

严格模式下: this指向undefined

非严格模式下: 1、this指向window 2、如果是对象调用,那么指向该对象,如果是函数调用,那么指向该函数(箭头函数除外,在箭头函数中,指向外层函数) 3、如果调用了apply、call、bind函数,则指向自定义指针空间

coloryjl avatar May 20 '19 08:05 coloryjl

非严格模式下:this指向window,函数内的this指向函数本身(箭头函数没有this,箭头函数的this就是外层代码的this) 严格模式下:this指向undefined this的指向可以通过apply,call,bind函数修改,也可以在外层函数中保存上层this

Timoeser avatar May 20 '19 09:05 Timoeser