概述
this 是JavaScript中的一个关键字,它是函数运行时,在函数体内自动生成的一个对象,只能在函数体内部使用。
this就是指针 ,指向调用函数的对象,这个对象我们称为函数执行的上下文对象。
全局上下文(在所有函数的外面)this指的是全局对象 window,
函数上下文(在某个函数的内部)this指的是当前函数所属的对象。
就是谁调用就指向谁。
调用方式
- 全局环境中this指向全局变量(window)
console.log(this);//window
- 函数中的this,由调用函数的方式来决定
- 如果函数是独立调用的,在严格模式(use strict)下是指向undefined的
"use strict";
function f(){
console.log(this);//undefined
}
f()
在非严格模式下,指向window
var name="全局";
function a(){
var name="函数内部";
console.log(this.name)//全局
console.log(this)//window
}
a()
- 如果这个函数是被某一个对象调用,那么this指向被调用的对象
let obj={
name:"obj的name",
fn:function(){
clg(this.name)//obj的name
}
}
obj.fn();
- 构造函数与原型里面的this
构造函数里的this以及原型里的this对象指的都是生成的实例。(由new决定)
通过new操作符可以初始化一个constructor的指向,new的作用域就是创建一个对象的实例,constructor也就是指向了一个新的执行环境“在这个对象之中”。
- 箭头函数
箭头函数按词法作用域来绑定它的上下文,所以this 实际上会引用到原来的上下文。
(箭头函数会保持它当前执行上下文的词法作用域不变,而普通函数则不会,箭头函数从包含它的词法作用域中 继承了this的值)。
箭头函数没有自己的this,指向外层作用域
var obj = {
foo() {
console.log(this);
},
bar: () => {
console.log(this);
}
}
obj.foo() // {foo: ƒ, bar: ƒ} 指向obj
obj.bar() // window
其他情况
全局下把对象赋值给变量时
把对象赋值给一个变量,调用该方法时,this 指向window
var name="全局name";
var obj= {
name:"obj的name",
fn:function(){
console.log(this.name); //全局name
}
}
//把对象赋值给一个变量
var test=obj.fn;
test()
个人理解:test全局下调用
包含多个对象,只指向上一级
var obj={
a:10,
b:{
a:12,
fn:function(){
console.log(this.a)
}
}
}
obj.b.fn()//12
this指向的是对象b
如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。
看下一个例子
var o = {
a:10,
b:{
fn:function(){
console.log(this.a); //undefined
}
}
}
o.b.fn();
尽管对象b中没有属性a,这个this指向的也是对象b,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。
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
j 在全局下调用
总结
this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的。
在js的严格模式中this指向的不是window
自执行函数
自执行函数的this指向window
var obj = {
foo: "test",
fn: function () {
var mine = this;//这个this是指向obj的,可以clg一下
console.log(this.foo); //test
console.log(mine.foo); //test
(function () {
console.log(this);//window
console.log(this.foo); //undefined
console.log(mine.foo); //test
console.log(mine);//object
})();
}
};
obj.fn();
测试一下有没有掌握
1
var a=1;
var obj={
b:function(){
console.log(a)
console.log(this.a)
}
}
obj.b()
1
undefined
2
var a=1;
var obj={
a:"obj里面的a",
b:function(){
console.log(a)
console.log(this.a)
}
}
obj.b()
1
obj里面的a
var a=1;
var obj={
a:"obj里面的a",
b:function(){
var a="bbb"
console.log(a)//bbb
console.log(this.a)
}
}
obj.b()
3
var a=1;
var obj={
a:"obj里面的a",
b:function(){
var t=this
console.log(a)
console.log(this.a)
console.log(t.a)
console.log(t)
}
}
obj.b()
1
obj里面的a
obj里面的a
{a: 'obj里面的a', b: ƒ}
4
var obj = {
a: 10,
b: this.a + 10,
//这里的this指向window(全局),a为undefined ==> undefined + 10 = NaN
fn: function () {
return this.a;
}
}
console.log(obj.b)
console.log(obj.fn())
NaN
10
5
var obj= {
user:"o的user",
fn:function(){
console.log(this.user); //o的user
}
}
var test=obj.fn;
test()//undefined
赋值给一个变量,最后指向全局
6
var obj={
a:10,
b:{
a:12,
fn:function(){
console.log(this.a)
}
}
}
obj.b.fn()
指向上一级 输出12
7
var o = {
a:10,
b:{
fn:function(){
console.log(this.a); //undefined
}
}
}
o.b.fn();
输出undefined,指向上一级
8
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); //window
}
}
}
var j = o.b.fn;
j();
最后是 j 调用的,指向window
9
function fn( ) {
'use strict';
var a = 1;
var obj = {
a: 10,
c: this.a + 20
//严格模式下,a指向undefined嘛,undefined.a报错
}
return obj.c;
}
console.log(fn()); //输出报错
严格模式下 this 指向 undefined
10
var obj = {
foo: "test",
fn: function () {
var mine = this;//这个this是指向obj的,可以clg一下
console.log(this.foo); //test
console.log(mine.foo); //test
(function () {
console.log(this.foo); //undefined
console.log(mine.foo); //test
console.log(this);//window
console.log(mine);//object
})();
}
};
obj.fn();
外部的函数this指向obj,内部的 自执行函数的 this 指向window
11
var a = 20;
var obj = {
a: 10,
getA: function () {
return this.a;
}
}
console.log(obj.getA()); //10
var test = obj.getA;
console.log(test()); //20 独立调用test
12
var a = 5;
function fn1(){
var a = 6;
console.log(a); //6
console.log(this.a); //5
}
function fn2(fn) {
var a = 7;
fn();
}
var obj = {
a: 8,
getA: fn1
}
fn2(obj.getA);
obj.getA();//6 8
13
function fn( ) {
'use strict';
var a = 1;
var obj = {
a: 10,
c: this.a + 20 //严格模式下,a指向undefined嘛,undefined.a报错
}
return obj.c;
}
console.log(fn()); //输出报错==》 a undefined
14
// 声明一个构造函数
function Person(name, age) {
this.name = name;
this.age = age;
console.log(this); //与下面的this是一样的,都是Person
}
// Person(); //this 指向window
Person.prototype.getName = function () {
console.log(this); //与上面的this是一样,都是Person
};
var p1 = new Person("test", 18);
p1.getName();
15
var obj = {
foo: "test",
fn: function(){
var mine = this;
console.log(this.foo); //test
console.log(mine.foo); //test
(function(){
console.log(this.foo); //undefined
console.log(mine.foo); //test
})();
}
};
obj.fn();
/**
(1) 在外部函数中, this 和 mine两者都指向了obj,因此两者都可以正确地引用访问foo;
(2)在内部函数中,this不再指向obj,this.foo 没有在内部函数中被定义,
而指向到本地的变量mine保持在范围内,并且可以访问
(在ES5之前,内部函数的this将指向全局的
window对象; 则作为ES5,内部函数中的this是未定义的。)
*/
16
function foo(){
console.log(this.a);
}
var a = 2;
var o = {
a:3,
foo: foo
};
var p = { a:4 };
o.foo(); //3
(p.foo = o.foo)(); //2
/**
相当于:
function w(){
p.foo = o.foo;
}
w();
此时的constructor指向window,调用这个w,这个w是在window下创建的,相当于
调用window.w(),所以constructor指向window。
*/
p.foo = o.foo;
p.foo(); //4 函数由p执行,那么constructor指向的就是对象p,谁调用就指向谁0.0
//this也就指向p, 因此this.a === p.a