-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
如何正确判断this的指向?(注意区分严格模式和非严格模式) #1
Comments
console.log(this) |
不使用 console alert 等的情况下~ |
如何判断this 指向 就需要找到这个函数的直接调用位置 找位置之后再确定this指向 |
默认情况下 严格模式绑定到undefined,非严格模式 绑定全局上 |
this指的是当前执行环境的上下文,非严格模式的全局对象绑定在window上面,在严格模式下,全局对象将无法使用默认绑定,因此this会绑定到undefined |
谁调用,this就指向谁;在严格模式下,this指向的是undeined,在非严格模式下this指向的是全局变量,通过一些特殊的方式可动态改变this,apply,call;而bind是让this再创建时就让他固定;箭头函数也可以改变this,指向的是当前全局变量 |
首先this并不会指向函数本身。 |
非严格模式 |
非严格模式 |
非严格模式下 |
总得来说:this指向执行主体 分几种情况:
|
function test(){
'use strict' //内部
console.log(this) // undefined
}
|
谁调用的this,this就指向谁, |
如何正确判断this的指向?一、严格模式( "use strict";)(一) 作为obj对象时this指向obj (二)作为function时this指向undefined (三)使用apply、call、bind调用this指向绑定对象的第一个参数 (四)箭头函数this指向上一层函数 二、非严格模式(一) 作为obj对象时,this指向obj(二)作为function时this指向function对象 (三)使用apply、call、bind调用this指向目标函数,null和undefined,指向全局对象(浏览器中是window),其余值指向被new Object()包装的对象 (四)使用构造函数调用this指向new生成的新对象 参考文章[【面试官问:JS的this指向】](https://juejin.im/post/5c0c87b35188252e8966c78a#heading-4)
|
对于JS代码中没有写执行主体的情况下,非严格模式默认都是window执行的,所以this指向的是window,但是在严格模式下,没有写执行主体,this指向是undefined |
首页一条原则是JS中的this代表的是当前行为执行的主体 |
学习了 感谢
…------------------ 原始邮件 ------------------
发件人: "wanglinyj"<notifications@github.com>;
发送时间: 2019年5月20日(星期一) 上午10:44
收件人: "YvetteLau/Step-By-Step"<Step-By-Step@noreply.github.com>;
抄送: "爱到最美是陪伴💏"<2549890204@qq.com>; "Comment"<comment@noreply.github.com>;
主题: 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.
|
单独函数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 对象方法中的
|
谢谢 学习了 写的非常详细 我会好好看好好学习一下的
…------------------ 原始邮件 ------------------
发件人: "wubetter"<notifications@github.com>;
发送时间: 2019年5月20日(星期一) 上午10:54
收件人: "YvetteLau/Step-By-Step"<Step-By-Step@noreply.github.com>;
抄送: "爱到最美是陪伴💏"<2549890204@qq.com>; "Comment"<comment@noreply.github.com>;
主题: 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.
|
全局环境无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。 函数(运行内)环境
|
1、如何正确判断this的指向?(注意区分严格模式和非严格模式)
对于直接调用 foo 来说,不管 foo 函数被放在了什么地方,this 一定是 window 对于箭头函数中的this bind,不知道大家是否考虑过,如果对一个函数进行多次 bind,那么上下文会是什么呢? let a = {} 函数转换下 // fn.bind().bind(a) 等于 bind多次绑定 输出的值任然是 fu 中的this永远是第一次bind决定的。所以结果是 window let datas={name:'hello'} 首先,new 的方式优先级最高,接下来是 bind 这些函数,然后是 obj.foo() 这种调用方式,最后是 foo 这种调用方式,同时,箭头函数的 this 一旦被绑定,就不会再被任何方式所改变。 -----搜索的看的某大佬的小册, |
在严格模式下,this指向是undefined;在非严格模式下,一是直接调用时,thi指向的是全局对象;二是方法调用时,this指向的是该方法的对象;三是new调用时,this指向新的对象;四是箭头函数中,this指向方法调用的对象。 |
this **非严格模式** this指向全局对象 window this永远指向最后调用的那个对象 也可以使用apply、call、bind改变 this 的指向 可以参考 https://juejin.im/post/59bfe84351882531b730bac2#heading-4 |
补充加深理解 1.如果为null或undefined,this指向window; 用伪代码来演示如下:if(hasStrict){ 一.正常的函数调用(默认绑定); 具体请看相关参考文章链接 |
非严格模式下:函数中this调用:this-----》window 方法中this调用:this-----》当前对象(嗲用方法的对象) 构造函数中this调用:this------》该构造函数的实例对象 借用方法调用:改变this的指向 分析this的问题,需要明白两点: 1.分析this是属于哪个函数 2.分析该函数是以什么模式被调用的 严格模式中,函数调用模式内部的this为:undefined |
1、全局作用域中的this |
如何判断this?(包括讨论在严格模式和非严格模式) 先不讨论严格模式和非严格模式,注意'use strict'要要么放在文件开头,要么放在函数内部,否则不起作用 JavaScript高级程序设计中有下面这一句话:
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、箭头函数调用 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] } |
严格模式下: 非严格模式下: |
非严格模式下:this指向window,函数内的this指向函数本身(箭头函数没有this,箭头函数的this就是外层代码的this) |
this的理解
|
this的指向可以按照以下顺序判断: 1. 全局环境中的 this浏览器环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象 window; node 环境:无论是否在严格模式下,在全局执行环境中(在任何函数体外部),this 都是空对象 2. 是否是
|
1、new绑定:函数是否通过new调用,是的话this绑定的是新创建的对象 |
其实大家的答案都是大同小异,我也不例外。我也差不错,我是这么记的 |
我想先说一下我的理解。 es6中,箭头函数中的this始终指向函数定义时的this,而非执行时,箭头函数中没有this绑定,必须通过查找作用域链来确定它的值,如果箭头函数被非箭头函数包含,则this指向的是最近一层非箭头函数的this,否则指向undefined。 call,apply,bind是可以改变this的指向的。他们第一个参数都为this指向的对象,当第一个参数为null和undefined时,this指向全局对象。call后面参数是一个个要传给函数的值;apply后面是一个要传给函数的参数组成的数组;bind和前两者不同,它在改变函数this指向之后并没有调用函数,而是需要手动调用;此外apply从第二个参数开始也是一个个要传给函数的参数值。 |
<script>
// 浏览器正常情况下
console.log(this === window) // true
</script>
<script>
// 函数调用
a = 10;
function fn1 () {
console.log(this.a)
}
fn1() // 10
b = 2
console.log(this.b) //2
function fn2 () {
this.b = 3
}
fn2()
console.log(this.b) // 3
</script>
<script>
// 方法调用
function test () {
console.log(this.x)
}
x = 2
var o = {}
o.x = 1
o.m = test
o.m() // 1
</script>
<script>
// 构造函数调用
x = 2
function test () {
this.x = 1
}
var o = new test()
console.log(x) // 2
</script>
<script>
// apply调用
x = 0
function test () {
console.log(this.x)
}
var o = {}
o.x = 1
o.m = test
o.m.apply(o) // 1
</script>
<script>
// 函数 apply调用
var zz = {};
zz.a = 1000;
a = 10;
function fn1 () {
console.log(this.a)
}
fn1.apply(zz) // 1000
b = 2
console.log(this.b) //2
function fn2 () {
this.b = 3
}
fn2.apply(zz)
console.log(this.b) // 2
</script>
<script>
// 函数 apply调用
var qqq = {
a: 1
}
var ttt = {
a: 2
}
var mmm = {
a: 3
}
function fq () {
console.log(this)
}
fq.bind(qqq).bind(ttt).bind(mmm)() // {a: 1}
</script>
<script>
// forEach
var arr = [1, 2, 3, 4]
var newarr = [5, 6, 7, 8]
var newnewarr = [9, 10, 11, 12]
arr.forEach(function (e, i, a) {
console.log(this) // newarr
}, newarr)
arr.forEach((e, i, a) => {
console.log(this) // window
}, newarr)
</script>
<script>
// 立即执行函数
(function () {
console.log(this) // window
})()
var o = {};
o.x = 999;
(function () {
console.log(this) // {x:999}
}).apply(o)
;(() => {
console.log(this) // window
})()
;(() => {
console.log(this) // window
}).apply(o)
</script>
<script>
'use strict'
console.log(this === window) // true
</script>
<script>
'use strict'
var k = {
a: 1,
b: 2,
c: 3
}
const fn1 = function () {
console.log(this)
}
fn1() // undefined
fn1.apply(k) // {a: 1, b: 2, c: 3}
k.m = fn1
k.m() // {a: 1, b: 2, c: 3, m: ƒ}
</script>
<script>
'use strict'
const o = {
a: 1,
b: 2,
c: 3
}
const fn2 = () => {
console.log(this)
}
fn2() // window
fn2.apply(o) // window
o.m = fn2
o.m() // window
</script>
<script>
'use strict'
const oo = {
d: function () {
console.log(this)
},
e: () => {
console.log(this)
}
}
const ooo = {
a: 1,
b: 2,
c: 3
}
oo.d() // {d: ƒ, e: ƒ}
oo.e() // window
oo.d.apply(ooo) // {a: 1, b: 2, c: 3}
oo.e.apply(ooo) // window
var xxx = oo.d
var yyy = oo.e
xxx() // undefined
yyy() // window
</script>
<script>
'use strict'
// forEach
var arr = [1, 2, 3, 4]
var newarr = [5, 6, 7, 8]
var newnewarr = [9, 10, 11, 12]
arr.forEach(function (e, i, a) {
console.log(this) // newarr
}, newarr)
arr.forEach((e, i, a) => {
console.log(this) // window
}, newarr)
</script> 简单列了
在ECMA内,
原生方法GetThisEnvironment找到当前提供关键字
注意:步骤2中的循环必须终止,因为列表的环境总是以全局环境这个绑定。 |
如何正确判断this指向首先,我们知道js运行时, 会产生维护一个调用栈。 在js引擎逐行执行代码的时候,会动态的去对这个栈进行维护(进入一个函数,产生一个调用栈, 也就是我们说的产生一个局部作用域, 函数运行完成,退出函数, 这个栈跟着也就弹出, 把控制权回到上一层)。那说this的时候,为什么要扯调用栈呢?
那问题来了,什么是调用位置? 调用位置指的是代码执行到这个地方的时候, 他的调用上下文是什么?当前环境是什么?让我们来看一个示例:
(这是一个调用栈的关系, 脑补一下栈的结构, 先进后出。global - a -> b -> c -> c(done) -> b(done) -> a(done) -> global) 在我们理解了调用位置后,获取调用位置。在调用过程中如何绑定this对象呢?四个规则. 四个规则: 规则1: 默认绑定 该规则优先级最低. 在全局环境下, this会被默认的指向全局对象.(浏览器的话就是window)
But, 这里有个问题是, 如果你使用了严格模式,this不会默认绑定到全局对象,而是被绑定到undefind 规则2: 隐式绑定 当我的this, 存在上下文环境, 并且该环境下this有指向的时候, 那么this, 指向该上下文.看个例子:
规则3: 显式绑定 call/apply/bind绑定 啊, 这里是不是要说这三个函数的不同之处?
这里的第二步就是显式绑定, 显示绑定时最常见的情况,也是我们预料中this的合理行为。这个不多说了。 规则4: new关键字绑定 啊, 这里是不是要说new关键字了。我记得有道面试题,问new做了什么事?
判定顺序:
PS: ES6要格外注意箭头函数, 箭头函数的this指向,大家可以看一下这个issues 反正我只记住了一句话: 所有的箭头函数都没有自己的this,都指向外层。然后放一个例子:
《你不知道的js》 真的是一本好书 啊, 果然不支持md语法.但是我存档用md啊.就这样吧. 晚安. |
严格模式: |
首先this是一个对象,JavaScript中万物都是对象 话说看小姐姐的例子,发现闭包中的变量不会被回收,有顺带复习了一下闭包的特性,666~~~ |
在严格模式下(严格模式是指函数单独调用时的内部,而不是函数的上层): 在非严格模式下: 使用箭头函数:this指向外层函数调用对象 |
如何正确判断 this 的指向?全局环境
// 在浏览器中, window 对象同时也是全局对象:
console.log(this === window); // true
a = 37;
console.log(window.a); // 37
this.b = "MDN";
console.log(window.b); // "MDN"
console.log(b); // "MDN" 普通函数调用
function test() {
console.log(this); // 全局对象
}
function testStrict() {
"use strict";
console.log(this); // undefined
} 箭头函数
(() => {
console.log(this); // 严格与非严格模式都指向 全局对象
})(); 箭头函数其他注意点:
对象方法调用
const cat = {
nickname: "Tom",
meow() {
console.log(`${this.nickname} say meow`);
}
};
cat.meow(); // Tom say meow
var meow = cat.meow;
meow();
/* 严格模式 */
// 报错
/* 非严格模式 */
// undefined say meow 类实例化
function Person() {
this.name = "haha";
console.log(this); // { name: 'haha' }
return Object.create(null);
}
var x = new Person();
console.log(x); // {}
// 注意, 这里的 x 和 构造函数中的 this 已经没有任何关系了 引用 MDN 中 new 操作符的操作 new
|
1.当函数作为一个对象的方法被调用时,this指向该对象; |
|
严格模式
非严格模式
箭头函数
|
如果要判断一个运行中函数的 this 绑定, 就需要找到这个函数的直接调用位置。 找到之后 new 调用:绑定到新创建的对象,注意:显示return函数或对象,返回值不是新创建的对象,而是显式返回的函数或对象。 ES6 中的箭头函数:不会使用上文的四条标准的绑定规则, 而是根据当前的词法作用域来决定this, 具体来说, 箭头函数会继承外层函数,调用的 this 绑定( 无论 this 绑定到什么),没有外层函数,则是绑定到全局对象(浏览器中是window)。 这其实和 ES6 之前代码中的 self = this 机制一样。 |
his的指向在函数创建的时候是决定不了的,在调用的时候才能决定,this 是在运行期进行绑定的分几种情况:
注 当this碰到return时,会有些变化
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例。
|
函数中的this指向和当前函数在哪定义和在哪执行的没有任何的关系。 |
谁调用了函数,this就指向谁,this即函数的调用者。
修改this指向的方式:
经典练习题: function Foo () {
getName = function () { alert(1) }
return this
}
Foo.getName = function () { alert(2) }
Foo.prototype.getName = function () { alert(3) }
var getName = function () { alert(4) }
function getName () { alert(5) }
//输入的值
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName(); 答案Foo.getName(); //2
getName(); //4
Foo().getName(); //1
getName();//1
new Foo.getName(); //2
new Foo().getName(); //3
new new Foo().getName(); //3 |
无论是否在严格模式下,在全局执行环境中(在任何函数体外部) this 都指向全局对象。 |
|
全局环境无论是否在严格模式下,在全局执行环境中(在任何函数体外部),
函数(运行内)环境在函数内部, 1.简单调用1.1 非严格模式:
1.2 严格模式:
2.函数通过
|
课代表啊! |
1、通过属性形式调用,this指向该调用的对象,比如obj.a(),this指向obj |
如何正确判断this的指向?首先我们要清楚this的指向确定是发生在调用的时候的,而不是声明this的时候。
一、默认绑定(严格/非严格模式)
二、隐式绑定当函数引用有上下文对象时,隐式绑定规则会把函数中的this绑定到这个上下文对象。对象属性引用链中只有上一层或者说最后一层在调用中起作用,this指向了这个上下文对象。
但是在隐式绑定某些情况下的this会指向window或者undefined。(即类似默认绑定)
三、显式绑定通过call 或者 apply方式。第一个参数是一个对象,相当于在调用函数时将这个函数的this绑定到这个对象。因为直接指定this的绑定对象,称之为显示绑定。
四、new绑定使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
五、箭头函数绑定箭头函数有两个方面的作用:更简短的函数并且不绑定this。
|
一般来讲,谁调用它,this就指向谁; |
①在浏览器下的this默认指向window对象(非严格模式),(严格模式)this为undefined(默认) |
我觉得第四点 任何函数的this 在函数定义时就已经指定好了。而且我觉得this的指向问题牵扯到作用域链的问题。箭头函数为何this指向外层,因为箭头函数本身无法形成作用域。只能向上查找。 |
你好,我这边在全局环境下定义了一个函数,log this的指向,在浏览器环境下log的是window(没问题),但是在node环境下,log的是 Objectglobal;出现{}的时候是,node环境下,obj.fn(),fn为箭头函数;这两者的指向应该是一样的,但是log的结果却不相同,是node环境的问题吗? |
为什么下面代码保存在一个 js 文件里,一个 html 引入这个 js 文件,然后 chrome 最新版浏览器打开这个本地的 html 文件后, this 还是指向了 window 对象? |
No description provided.
The text was updated successfully, but these errors were encountered: