Vuejs和Javascript中的this变量的理解
文章目录1 javascript1.1 对象中this1.2 函数中this2 Vuejs2.1 vue组件中2.2 回调函数2.3 箭头函数1 javascript1.1 对象中this//test.jsvar out = {function inner(){this}}// 此时函数中的this表示out对象1.2 函数中this//test.jsfunction inner(){this}/
文章目录
1 javascript
1.1 全局环境下
在全局环境下,this
始终指向全局对象(window
), 无论是否严格模式;
console.log(this.document === document); // true
// 在浏览器中,全局对象为 window 对象:
console.log(this === window); // true
this.a = 37;
console.log(window.a); // 37
1.2 对象中this
对象内部方法的this
指向调用这些方法的对象
- 函数的定义位置不影响其
this
指向,this
指向只和调用函数的对象有关。 - 多层嵌套的对象,内部方法的
this
指向离被调用函数最近的对象
(window
也是对象,其内部对象调用方法的this
指向内部对象, 而非window)
var Person = {
name: "hahah",
say:function(){
console.log(this);
}
}
测试一,此时是Person
对象调用:
console.log(Person.name);
console.log(Person.say());
测试结果:
测试二,此时是window
对象调用:
var f = Person.say;
console.log(f());
测试结果:
1.3 函数中this
普通函数中的this
:
this
总是代表它的直接调用者(js
的this
是执行上下文), 例如obj.func
,那么func
中的this
就是obj
- 在默认情况(非严格模式下,未使用
use strict
),没找到直接调用者,则this
指的是window
(约定俗成) - 在严格模式下,没有直接调用者的函数中的
this
是undefined
- 使用
call,apply,bind
(ES5新增)绑定的,this
指的是绑定的对象 - 构造函数中的
this
与被创建的新对象绑定,当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this
看调用问题:
var Person = function (){
this.name = "haha";
this.say = function(){
console.log(this);
}
}
Person调用:
var p = new Person();
console.log(p.say());
结果----------------
Person {name: "haha", say: ƒ}
window调用:
var p = new Person();
var say = p.say;
console.log(say());
结果----------------
Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}
1.4 箭头函数
箭头函数中的this
- 箭头函数没有自己的
this
, 它的this
是继承而来; 默认指向在定义它时所处的对象(宿主对象)
,而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在setTimeout
,setInterval
中方便的使用this
- 箭头函数中,
this
指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this
- 箭头函数没有自己的
this
,它的this是继承而来
,默认指向在定义它时所处的对象(宿主对象)。
看例子:
例子一,箭头函数:
此处是箭头函数,此时的this
是继承而来,指向在定义它时所处的对象
function Person (){
this.name = "haha";
setTimeout(()=>{
console.log(this);
},1000);
}
var p = new Person();
结果------------ 一秒后
Person {name: "haha"}
例子二,普通函数:
箭头函数修改为普通函数后,就看谁调用,就指向谁了,由于setInterval跟setTimeout调用的代码运行在与所在函数完全分离的执行环境上,setTimeout
是window
对象的因此指向它
function Person (){
this.name = "haha";
setTimeout(function(){
console.log(this);
},1000);
}
var p = new Person();
结果------------一秒后
Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}
更多this
理解可以参考JavaScript面向对象编程:(1)面向对象概述
1.5 例子和总结
看了上面的基本介绍对于this
有了基本认知,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象
- 如果一个函数中有
this
,但是它没有被上一级的对象所调用,那么this
指向的就是window
,这里需要说明的是在js的严格版中this指向的不是window
- 如果一个函数中有
this
,这个函数有被上一级的对象所调用,那么this
指向的就是上一级的对象 - 如果一个函数中有
this
,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this
指向的也只是它上一级的对象,例子3可以证明,具体讲解需要看下面例子 new
关键字可以改变this
的指向- 如果函数
return
返回值是一个对象,那么this
指向的就是那个返回的对象,如果返回值不是一个对象那么this
还是指向函数的实例,还有一点如果返回null
,虽然也是对象,但this
还是指向那个函数实例
,因为null
比较特殊
1.5.1 例一全局对象
function a(){
var user = "追梦子";
console.log(this.user); //undefined
console.log(this); //Window
}
a();
按照我们上面说的this最终指向的是调用它的对象,这里的函数a实际是被Window对象所点出来的,下面的代码就可以证明
function a(){
var user = "追梦子";
console.log(this.user); //undefined
console.log(this); //Window
}
window.a();
和上面代码一样吧,其实alert也是window的一个属性,也是window点出来的
1.5.2 例二对象调用
var o = {
user:"追梦子",
fn:function(){
console.log(this.user); //追梦子
}
}
o.fn();
这里的this
指向的是对象o
,因为调用这个fn
是通过o.fn()
执行的,那自然指向就是对象o
,这里再次强调一点,this
的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁,一定要搞清楚这个。
1.5.3 例三嵌套调用
var o = {
user:"追梦子",
fn:function(){
console.log(this.user); //追梦子
}
}
window.o.fn();
这段代码和上面的那段代码几乎是一样的,但是这里的this
为什么不是指向window
,如果按照上面的理论,最终this
指向的是调用它的对象,这里先说个而外话,window
是js
中的全局对象,我们创建的变量实际上是给window
添加属性,所以这里可以用window点o对象
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12
}
}
}
o.b.fn();
这里同样也是对象o
点出来的,但是同样this
并没有执行它,结合上面的总结看例子就可以了
var o = {
a:10,
b:{
// a:12,
fn:function(){
console.log(this.a); //undefined
}
}
}
o.b.fn();
尽管对象b
中没有属性a
,这个this
指向的也是对象b
,因为this
只会指向它的上一级对象,不管这个对象中有没有this
要的东西
1.5.4 例四赋值引用调用
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); //window
}
}
}
var j = o.b.fn;
j();
这里this
指向的是window
,是不是有些蒙了
this
永远指向的是最后调用它的对象
,也就是看它执行的时候是谁调用的,例子4中虽然函数fn
是被对象b
所引用,但是在将fn
赋值给变量j
的时候并没有执行所以最终指向的是window
,这和例子3是不一样的,例子3是直接执行了fn
。
1.5.5 例五new构造调用
function Fn(){
this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子
这里之所以对象a
可以点出函数Fn
里面的user
是因为new
关键字可以改变this
的指向,将这个this
指向对象a
,为什么说a是对象
,因为用了new
关键字就是创建一个对象实例,理解这句话可以想想我们的例子3,我们这里用变量a
创建了一个Fn
的实例(相当于复制了一份Fn
到对象a
里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn
的是对象a
,那么this
指向的自然是对象a
,那么为什么对象Fn
中会有user
,因为已经复制了一份Fn函数
到对象a
中,用了new
关键字就等同于复制了一份。
为什么this
会指向a
?首先new
关键字会创建一个空的对象,然后会自动调用一个函数apply
方法,将this
指向这个空对象,这样的话函数内部的this
就会被这个空的对象替代
1.5.6 例六return和this
返回空对象
function fn()
{
this.user = '追梦子';
return {};
}
var a = new fn;
console.log(a.user); //undefined
返回空函数
function fn()
{
this.user = '追梦子';
return function(){};
}
var a = new fn;
console.log(a.user); //undefined
返回一个值
function fn()
{
this.user = '追梦子';
return 1;
}
var a = new fn;
console.log(a.user); //追梦子
返回undefined
function fn()
{
this.user = '追梦子';
return undefined;
}
var a = new fn;
console.log(a.user); //追梦子
console.log(a); //fn {user: "追梦子"}
返回null
function fn()
{
this.user = '追梦子';
return null;
}
var a = new fn;
console.log(a.user); //追梦子
2 Vuejs
2.1 vue组件中
在Vue
所有的生命周期钩子方法
(如beforeCreate
,created
,beforeMount
,mounted
,beforeUpdate
, updated
,beforeDestroy
以及destroyed
)里使用this
,this
指向调用它的Vue
实例,即(new Vue
)
new Vue({
data: {
a: 1
},
created: function () {
console.log('a is: ' + this.a)
}
methods: {
plus: function () {
this.a++
}
}
});
vue
组件或者实例中,不管是生命周期钩子函数created
还是自定义函数plus
,他们中的this
都是指当前vue
实例
2.2 回调函数
methods: {
searchLocations: function() {
var address = this.search
var geocoder = new window.google.maps.Geocoder()
geocoder.geocode({
address: address
}, function(results, status) {
if (status === window.google.maps.GeocoderStatus.OK) {
this.buscarLojas(results[0].geometry.location)
}
})
},
buscarLojas: function(center) {
console.log(center)
}
}
此时回调函数function(results, status)
会重新将this
指向匿名对象
(类比java匿名类
),所以其中的this
指代父级组件,执行this.buscarLojas
会报错找不到函数
2.3 箭头函数
箭头函数
没有自己的this
, 它的this
是继承而来; 默认
指向在定义它时所处的对象(宿主对象
),而不是执行时的对象
methods: {
searchLocations: function () {
var address = this.search
var geocoder = new window.google.maps.Geocoder()
geocoder.geocode({address: address}, (results, status) => {
if (status === window.google.maps.GeocoderStatus.OK) {
this.buscarLojas(results[0].geometry.location)
} else {
alert(address + ' not found')
}
})
},
buscarLojas: function (center) {
console.log(center)
},
group1:()=>{
//ES6的箭头函数写法,箭头函数没有自己的this,它的this事继承来的,指向在定义它时所处的宿主对象,在这里this指向window。
this.......
},
}
箭头函数
被绑定到父级上下文
,因此其中的this
会指向父级组件,针对情况三中的问题,将回调函数中的function
改成箭头函数,会将this
从匿名对象重新指向外部的vue
组件
更多推荐
所有评论(0)