javascript基础之this指针
越往后面学越发现基础的重要性,所以打算重新过一遍基础,之后出几个vue和react的实战教程。
ok,严归正传。
首先什么是this
this是执行上下文创建时确定的一个在执行过程中不可改变的变量。
总之记住一句话this的指向由以执行时候的上下文决定的而非定义时的上下文
看过一本书叫《JavaScript语言精粹》,里面把this的出现场景为4类,当然那是在es6出来之前,不过也可以表示基本的用法了,在es6出来之后出现箭头函数,所以一共是5种:
- 有对象的就指向该对象
- 没有对象的就指向全局对象,在非严格模式下指向window
- 有new构造函数的就指向new完之后的新对象
- 通过apply或者bind或者call改变this指向的对象
- 出现箭头函数的时候,this指向为定义时的上下文对象而非指向时,并且不能被call改变
函数有对象的时候就指向该对象
let name = 'bob';
let obj = {
name,
getName(){
console.log(this.name);
}
};
console.log(obj.getName()); //=>bob
因为getName()属于对象obj,并且由obj进行调用,所以毫无疑问是指向obj这个对象,ok,我们再看一个例子
var name = 'jay';
var obj = {
name:'bob'
getName(){
console.log(this.name);
}
};
let t = obj.getName;
console.log(t()); // => jay
如上,为什么这次t函数打印出来的值是jay?excuse me?
其实要理解也好简单,当执行t()的时候(在非严格模式下)其实t其实是属于全局对象(在浏览器环境)也就是window,而var name = 'jay'为全局变量,所以输出jay也不奇怪了。
没有对象的就指向全局对象,在非严格模式下指向window
var name = 'bob';
var obj = {
name,
getName:function(){
function otherName(){
return this.name;
}
console.log(otherName());
}
};
obj.getName(); // =>bob
otherName随便是在obj的getName中定义的,但是它还是一个普通函数,他的this其实和
var name = 'bob';
function otherName(){
return this.name;
}
console.log(otherName()); // =>bob
执行效果一样的,他的this的指向其实是undefined,在非严格模式下,当this指向undefined的时候其实会自动转化成window对象(在浏览器中)。
ok,让我们再看一种情况
var name = 'bob';
function otherName(){
"use strict"
return this.name;
}
console.log(otherName()); // Uncaught TypeError: Cannot read property 'name' of undefined
这个时候会抛出一个错误,因为在严格模式下当this指针指向undefined的时候不会自动转化成window对象。
有new构造函数的就指向new完之后的新对象
首先什么是构造函数,其实可以用一句话去概括:
构造函数其实就是用来新建对象的函数
JavaScript本身就为我们定义了几个常用的构造函数,你肯定认识 比如Function, Object, Array, Date等等,只不过我们平常object,function都不是用new Function,new Object,而是用他的语法糖比如
var obj = {} 其实等同于 var obj = new Object();
function Human(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
this.common = function(){
console.log('名字为'+this.name);
}
}
var h = new Human('bob',25,'sex');
h.common(); // => 名字为bob
有new构造函数的就指向new完之后的新对象,此时的this指向的是他new出现来的对象h。
通过apply或者bind或者call改变this指向的对象
由于函数具有函数作用域,所以有时候我们需要引用外层作用域的时候通常用的方法是call,apply,和bind这三兄弟
首先我们来看看call,老样子先看代码
var a = {
user:"bob",
fn:function(){
console.log(this.user);
}
}
var b = {
user:'jay'
}
a.fn.call(b); // => jay
如果不调用call,我们直接使用a.fn的话将会输出bob,因为fn这个方法是a这个对象定义出来的,所以this指向是a这个对象,但是当我们使用了call之后this指针指向的对象就变成b了,于是乎也不难理解为什么输出的user是jay了。
简介一下call的用法:
fn.call(obj,argument-1,argument-1,...)
是以obj这个对象去代替fn的this指针也就时fn的this指针指向obj,后面的argument-1,argument-1是形参
apply和call的用法基本相同,不同点是apply调用传形参的时候穿的是数组或者是类数组,如下:
fn.apply(obj,[argument-1,argument-1,...])
至于bind和call或者apply的区别,我也举一个例子
var a = {
user:"bob",
fn:function(){
console.log(this.user);
}
}
var b = {
user:'jay'
}
var c = a.fn.bind(b);
c(); // => jay
从上面这个例子可以得出一个结论:
其实call和apply方法,都是对函数的直接调用,但是bind()方法需要加上()来执行。
出现箭头函数的时候,this指向为定义时的上下文对象而非指向时,并且不能被call改变
首先我们先看一个例子:
var obj = {name:'bob'};
var name = 'jay';
var sayName = () => console.log(this.name);
sayName(); // => jay
sayName.call(obj); //jay
由上面的例子我们可以看出来此时this指针在用call改变了之后指向的依然是全局对象(非严格浏览器环境中是window)而非obj。
ok,至此this指针的用法总结完毕。
后记
以上this的用法都为个人总结,如有不当之处还请指出
转载请注明出处.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。