攻城狮-web

javascript之this的指向

说明

在学习js的过程中,最难搞清楚的就是this的指向谁?this本质上可以看做是函数调用时的运行环境对象-content.为执行中的函数判定this绑定需要找到这个函数的直接调用点。
谁调用指向谁,找不到调用的就指向window
new,call apply改变this的指向
a.call(b)将函数的内部指向b,同时调用了a函数
argument是一个传参数的集合,类数组,用在所传递的参数不确定的情况下

案例说明

1
2
3
4
1、new绑定,使用新构建对象作为运行环境
function fn(a){
this.name = a; //this
}

使用new发生的几件事

  1. 新建一个对象
  2. 将这个对象加入原型链
  3. this绑定
  4. 一般返回这个新对象
  • 函数结合new当做构造函数使用,本质也是函数调用,表达式的值等于return的结果
1
2
3
4
5
6
function fun(){
var name = "Beter"
console.log(this.name) //undefine
console.log(this) //window
}
fun()
  • this最终指向的是调用它对象,这里的函数fun实际是被window对象所指出的。
1
2
3
4
5
6
7
var o = {
user:'beter',
fn:function(){
console.log(this.user) //beter
}
}
o.fn();

在这里this为什么不是指向window.解释一下,window是js中 的全局变量,我们创建的变量实际上就是给window添加属性,所以这里的window指向o

1
2
3
4
5
6
7
8
9
10
11
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12
console.log(this.b); //undefined
}
}
}
o.b.fn();

  • 情况1:如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是window,这里需要说明的是在js的严格版中this指向的不是window
  • 如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象
  • 如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

特殊情况

1
2
3
4
5
6
7
8
9
10
11
12
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this) //window
}
}
}
var j = o.b.fn
j()

这里this指向的是window,是不是有些蒙了?其实是因为你没有理解一句话,这句话同样至关重要。this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子4中虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window
构造函数中的this

1
2
3
4
5
function fun(){
this.user = "beter"
}
var a = new fun();
console.log(a.user) //beter

这里的对象a可以点进函数fn里面的user是因为new关键字可以改变this的指向,将这个this指向a,为什么说a是对象,因为new关键字就是创建一个实例对象,这里用变量a创建一个fun的实例(相当于复制了一份fun到对象a里面),调用这个函数fun的是对象a,this就自然指向对象a。
/除了new外,自行改变this指向的还有call,apply,bind/
升级代码

1
2
3
4
5
6
var x = 2;
  function test(){
    this.x = 1;
  }
  var o = new test();
  alert(x); //2

当this遇上return

1
2
3
4
5
6
7
function fn()
{
this.user = '追梦子';
return {};
}
var a = new fn;
console.log(a.user); //undefined

继续看

1
2
3
4
5
6
7
function fn()
{
this.user = '追梦子';
return function(){}; //这里的function是一个对象,只是未执行
}
var a = new fn;
console.log(a.user); //undefined

demo不能停

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function fn()
{
this.user = '追梦子';
return 1;
}
var a = new fn;
console.log(a.user); //追梦子
function fn()
{
this.user = '追梦子';
return undefined;
}
var a = new fn;
console.log(a.user); //追梦子

如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回不是一个对象那么this指向函数的实例

1
2
3
4
5
6
7
function fn()
{
this.user = '追梦子';
return null;
}
var a = new fn;
console.log(a.user); //追梦子

虽然null也是对象,但是this依旧指向函数的实例。

函数还可以作为某个对象的方法调用,这时this就指这个上级对象

1
2
3
4
5
6
7
function test(){
    alert(this.x);
  }
  var o = {};
  o.x = 1;
  o.m = test;
o.m(); // 1

对象中的this指向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
demo1---
var obj={name:'jjc'}
var obj1 = {
name:"monkey",
fn:function(){
console.log(this.name)
}
}
obj1.fn(); //monkey
obj1.fn.call(obj); //jjc
demo2---
var obj={
name:'jiajiac',
fn:function(){
console.log(this.name) //jiajiac
}
}
obj.fn()
demo3---
var name = 'guiyanhuaichao';
var obj={
name:'lige-xin',
fn:function(){
var name = this.name;
console.log(name.name) //fengjun
alert(name) //guiyanhuaichao
}
}
obj.fn()

对应事件的调用

1
2
3
4
var btn = document.querySelector('button');
btn.onclick = function(){
console.log(this) //this指向btn/对应的元素
}

全局调用函数内部的this

1
2
3
4
function Fun(){
console.log(this) //指向window
}
Fun() //window.Fun()

定时器会将this->window

1
2
3
4
5
6
7
8
var btn = document.querySelector('button');
btn.onclick = function(){
console.log(this) //this指向btn/对应的元素
setTimeout(function(){
console.log(this) //window 全局变量,对于任何时间的设置都会指向window
},1000)
}

对象下面设置的定时器依旧指向window

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var name = 'houzi',sex='男',other='basket'
var obj={
name:'贾己超',
sex:'男',
other:'篮球',
fn:function(){
var _this = this;
console.log(this.name) //jjc
setTimeout(function(){
alert(_this.sex) //男 这里指向全局变量
alert(_this.other) //basket 这里指向全局变量
},500)
}
}
obj.fn()