We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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
javascript中的this是啥东西?为啥我们经常被他搞得晕头转向不知所以?他是恶魔?是天使 ?是怪胎?让我们一起来揭开它那神秘的面纱。
首先this是Javascript语言的关键字之一,指函数运行时的当前对象。那既然和函数运行有关,js中函数有哪些调用模式呢?
this
运行
我擦,有木有一千只草泥马在心里蹦腾不息,人家是要弄懂this,你这又是整的哪一出
我们慢慢来,一步步从这些调用模式中探究this这个神奇的远古神兽
函数调用 即 functionName () 模式,这也是我们使用的最多的一种方式,其属于全局调用,浏览中默认情况下函数内部的this指向window,当然是在非严格模式下。
functionName ()
window
this.name = 'qianlong'; function showName () { console.log(this.name); console.log(this === window); } showName() // qianlong // true
当一个函数作为对象的某个属性方法被调用的时候
var obj = { name: 'qianlong', showName: function () { console.log(this.name); } }; obj.showName(); // qianlong
可以看出this指向是obj这个对象,其实本质上讲函数调用形式内部this就是指向调用它的那个对象
上面的例子相当于
window.showName()
这也是为什么可以读取到全局定义的name属性的原因。
再来
var showName = function () { console.log(this.name); }, obj = { name: 'qianlong', showName: showName }; obj.showName();
这个时候输出的是什么呢
结果是不变的,在js中,一切都是对象,而这里也只是将,obj的showName属性指向,showNmae函数的引用地址。
继续
当我们把showName方法赋值给了一个变量,又会有什么事情发生呢?
showName
var obj = { name: 'qianlong', showName: function () { console.log(this.name); } }; var tempShowName = obj.showName; tempShowName() // undefined
为什么不是期望的那样输出 qianlong呢。obj的showName方法是一个对象,当把它赋值给了tempShowName变量,此时便和obj没有什么关系了,而这个时候的调用和下面是等价的。
window.tempShowName()
window上此事并没有name属性,自然输出是undefined。
name
undefined
当使用 new 去调用一个构造函数的时候,内部的this,指向的是实例化出来的对象。
new
var Person = function (name, sex) { this.name = name; this.sex = sex; console.log(this); }; var p1 = new Person('qianlong', 'boy'); // Person {name: 'qianlong', sex: 'boy'};
构造函数也是函数,所以当你用普通调用方式调用时
var Person = function (name, sex) { this.name = name; this.sex = sex; console.log(this); }; Person('qianlong', 'boy'); // 这个时候相当于给window对象添加了name和sex两个属性。 window.name // 'qianlong' window.sex // 'boy'
使用call和apply方式去调用一个函数的时候,内部的this指向的是传进来的第一个参数,当第一个参数是undefined或者null的时候,依旧指向window
null
关于call和apply欢迎查看另一篇文章
js中call、apply、bind那些事
var showName = function () { console.log(this); }; showName() // window showName.call(undefined) // window showName.call(null) // window showName.call({name: 'qianlong'}) // {name: 'qianlong'}
在 ES6 的新规范中,加入了箭头函数,它和普通函数最不一样的一点就是 this 的指向,普通函数中的this,是运行时候决定的,而箭头函数却是定义时候就决定了。
var obj = { name: 'qianlong', showName: function () { console.log(this.name); }, showNameLater: function () { setTimeout(() => { console.log(this.name); }, 1000) } }; obj.showNameLater(); // qianlong
var obj = { name: 'qianlong', showName: () => { console.log(this.name); } }; obj.showName(); // undefined
一些坑
var obj = { name: 'qianlong', showName: function () { console.log(this.name); }, showNameLater: function () { setTimeout(this.showName, 1000); } }; obj.showNameLater(); // undefined
这里在执行setTimeout这个函数的时候传了obj的showName函数作为第一个参数,其效果与
var showName = obj.showName
是相同的。而setTimeout内部其实也是执行了传进去这个函数而已,即。
showName();
还记得这种调用方式和window.showName()是类似的效果吗?这个时候输入为undefined也就好理解了。
那么怎么解决这个问题呢,毕竟我们期望的效果是输出qianlong。
qianlong
var obj = { name: 'qianlong', showName: function () { console.log(this.name); }, showNameLater: function () { var self = this; setTimeout(function () { self.showName(); }, 1000); } }; obj.showNameLater();
或者
var obj = { name: 'qianlong', showName: function () { console.log(this.name); }, showNameLater: function () { setTimeout(this.showName.bind(this), 1000); } }; obj.showNameLater();
尼玛坑爹啊,居然还是因为你。
'use strict'; function show() { console.log(this); } show(); // undefined setTimeout(show, 1); // window
在严格模式下面,函数调用的时候没有指定this的情况下,内部this的表现为undefined,但是setTimeout却不同,其内部默认还是指向window。
var Person = function (name, sex) { this.name = name; this.sex = sex; }; var p1 = new Person.call({}); // Uncaught TypeError: Person.call is not a constructor
这里报错了,原因是我们去 new 了 Person.call 函数 ,这里的函数不是一个构造函数;
当然解决方式也是有的。
var Person = function (name, sex) { this.name = name; this.sex = sex; }; var p1 = new (Person.bind({}))('qianlong', 'sex'); // Person {name: "qianlong", sex: "sex"}
var show = (str) => { console.log(str); console.log(this); }; show('qianlong'); // qianlong // window show.call({name: 'qianlong'}, 'qianlong'); // qianlong // window
可以看到使用call来手动改变箭头函数中的this的时候,无法成功。 箭头函数中的 this 在定义它的时候已经决定了(执行定义它的作用域中的 this),与如何调用以及在哪里调用它无关,包括 (call, apply, bind) 等操作都无法改变它的 this。
文章可能有些疏漏与错误之处,欢迎各位指正。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
他是个啥
我擦,有木有一千只草泥马在心里蹦腾不息,人家是要弄懂this,你这又是整的哪一出
我们慢慢来,一步步从这些调用模式中探究this这个神奇的远古神兽
纯粹的函数调用
对象的方法调用
可以看出
this
指向是obj这个对象,其实本质上讲函数调用形式内部this
就是指向调用它的那个对象上面的例子相当于
这也是为什么可以读取到全局定义的name属性的原因。
再来
这个时候输出的是什么呢
结果是不变的,在js中,一切都是对象,而这里也只是将,obj的showName属性指向,showNmae函数的引用地址。
继续
当我们把
showName
方法赋值给了一个变量,又会有什么事情发生呢?为什么不是期望的那样输出 qianlong呢。obj的showName方法是一个对象,当把它赋值给了tempShowName变量,此时便和obj没有什么关系了,而这个时候的调用和下面是等价的。
window上此事并没有
name
属性,自然输出是undefined
。构造函数调用
构造函数也是函数,所以当你用普通调用方式调用时
apply、call调用
关于call和apply欢迎查看另一篇文章
js中call、apply、bind那些事
箭头函数
一些坑
这里在执行setTimeout这个函数的时候传了obj的showName函数作为第一个参数,其效果与
是相同的。而setTimeout内部其实也是执行了传进去这个函数而已,即。
还记得这种调用方式和
window.showName()
是类似的效果吗?这个时候输入为undefined也就好理解了。那么怎么解决这个问题呢,毕竟我们期望的效果是输出
qianlong
。或者
在严格模式下面,函数调用的时候没有指定this的情况下,内部this的表现为
undefined
,但是setTimeout却不同,其内部默认还是指向window。这里报错了,原因是我们去 new 了 Person.call 函数 ,这里的函数不是一个构造函数;
当然解决方式也是有的。
可以看到使用call来手动改变箭头函数中的this的时候,无法成功。 箭头函数中的 this 在定义它的时候已经决定了(执行定义它的作用域中的 this),与如何调用以及在哪里调用它无关,包括 (call, apply, bind) 等操作都无法改变它的 this。
结语
The text was updated successfully, but these errors were encountered: