在面向对象的语言中(例如Java,C#等),this 含义是明确且具体的,即指向当前对象。一般在编译期绑定。 
然而js中this 是在运行期进行绑定的,这是js中this 关键字具备多重含义的本质原因。下面就让我们一起来分析一下具体情况。 
由于js中this 是在运行期进行绑定的,所以js中的 this 可以是全局对象、当前对象或者任意对象,这完全取决于函数的调用方式。JavaScript 中函数的调用有以下几种方式:

  • 作为对象方法调用
  • 作为函数调用
  • 作为构造函数调用
  • 使用 apply 或 call 调用

JavaScript this决策树

 
根据这个决策树我们需要进行两步判断: 
1.函数调用是用new进行调用的吗?如果是,则this指向新创建的对象,否则,进入”否”分支; 
2.判断该函数是否是用dot(.)进行调用的,如果是,则即进入”是”分支,即this指向dot(.)之前的对象;否则this指向全局对象window. 
demo1:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
function test(a){
this.a = a;//相当于window.a
}
test(3);//这里相当于window.test(3)
//所以test函数中的this指向了window
console.log(a);//3 这里相当于与访问window.a
</script>
</body>
</html>

demo2: 
对于say方法中的sayA和sayB中的this来说:不是通过new操作符来调用的,也没有通过dot(.)来调用,因此this指向window

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
var obj = {
a:0,
b:0,
say:function(a,b){
var sayA = function(a){
console.log(this);//Window
this.a = a;
};
var sayB = function(b){
console.log(this);//Window
this.b = b;
};
sayA(a);
sayB(b);
}
}
obj.say(1,1);
console.log(obj.a+"--"+obj.b);//0--0
console.log(window.a+"-----"+window.b);//1-----1
</script>
</body>
</html>

demo3:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>面试题</title>
</head>
<body>
<script type="text/javascript">
function Person(name,age){
this.name = name;
this.age = age;
}
var person1 = new Person("lisi",18);
console.log(person1.name);//lisi
var person2 = Person("wangwu",12);
//person2是undefined
// console.log(person2.name);//Uncaught TypeError: Cannot read property 'name' of undefined
console.log(window.name);//wangwu
//Person("wangwu",12)相当于window.Person("wangwu",12)
</script>
</body>
</html>

demo4: 
apply 和 call 这两个方法切换函数执行的上下文环境(context),即可以改变this指向。obj1.say.call(obj2,3,3)实际上是obj2.say(3,3),所以say中的this就指向了obj2

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
function Test(a,b){
this.a = a;
this.b = b;
this.say = function(a,b){
this.a = a;
this.b = b;
}
}
var obj1 = new Test(1,1);
var obj2 = {a:2,b:2};
obj1.say.call(obj2,3,3);
console.log(obj2.a+"--"+obj2.b);//3--3
</script>
</body>
</html>

demo5: 
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象.当然这句话不完全准确,因为在不同环境下情况就会有不同。下面我们就来分析一下各种情况。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
// 这里的函数test实际是被Window对象调用的
function test(){
var name = "lisi";
console.log(this.name);//undefined
console.log(this);//Window
}
test();//这里相当于window.test();
</script>
</body>
</html>

demo6: 
如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。 
这个例子就是指向上一级对象obj

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
var obj = {
name:"lisi",
sayName:function(){
console.log(this.name);//lisi
}
}
obj.sayName();
</script>
</body>
</html>

demo7: 
对象字面量obj={} 
变量obj其实也是window对象的属性 
所以可以这样来调用window.obj.sayName(); 
如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,这里this指向obj,而不是window

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
var name = "wangwu";
var obj = {
name:"lisi",
sayName:function(){
console.log(this.name);//lisi
}
}
window.obj.sayName();
</script>
</body>
</html>

demo8: 
如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
var obj = {
name:"wangwu",
objInner:{
name:"lisi",
sayName:function(){
console.log(this.name);//lisi
}
}
}
obj.objInner.sayName();
</script>
</body>
</html>

demo9: 
尽管对象objInner中没有属性name,这个this指向的也是对象objInner,因为this只会指向它的上一级对象,不管这个对象中有没有this要的东西。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
var obj = {
name:"wangwu",
objInner:{
// name:"lisi",
sayName:function(){
console.log(this.name);//undefined
}
}
}
obj.objInner.sayName();
</script>
</body>
</html>

demo10: 
从这个例子我们可以看出:this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的 
在这个例子中虽然函数sayName是被对象objInner所引用,但是在将sayName赋值给变量fn的时候并没有执行,所以this最终指向的是window对象。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>this指向</title>
</head>
<body>
<script type="text/javascript">
var obj = {
name:"wangwu",
objInner:{
name:"lisi",
sayName:function(){
console.log(this.name);//undefined
console.log(this);//Window
}
}
}
var fn = obj.objInner.sayName;
fn();
</script>
</body>
</html>

demo11: 
对象person可以点出构造函数中的name是因为new关键字可以改变this的指向,将这个this指向对象person. 
这里new Person()创建了一个Person对象的实例,并赋值给了变量person

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>构造函数版this</title>
</head>
<body>
<script type="text/javascript">
function Person(){
this.name = "lisi";
}
var person = new Person();
console.log(person.name);//lisi
</script>
</body>
</html>

demo12:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>当this碰到return</title>
</head>
<body>
<script type="text/javascript">
/*
如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例
*/
function fn2(){
this.username = "lisi";
return {};
}
var obj = new fn2;
console.log(obj);//Object{}
console.log(obj.username);//undefined
function fn1(){
this.username = '王五';
return function(){};
}
var b = new fn1;
console.log(b);//function(){}
console.log(b.username);//undefined
function fn()
{
this.username = '王五';
return 1;
// return undefined;
}
var a = new fn;
console.log(a);//fn {username: "王五"}
console.log(a.username); //王五
//虽然null也是对象,但是在这里this还是指向那个函数的实例,因为null比较特殊
function fn3()
{
this.username = '王五';
return null;
}
var a = new fn;
console.log(a);//fn {username: "王五"}
console.log(a.username); //王五
</script>
</body>
</html>

js中this指向学习总结的更多相关文章

  1. JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解

      前  言 JRedu 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于 ...

  2. 前端js中this指向及改变this指向的方法

    js中this指向是一个难点,花了很长时间来整理和学习相关的知识点. 一. this this是JS中的关键字, 它始终指向了一个对象, this是一个指针; 参考博文: JavaScript函数中的 ...

  3. 关于js中this指向的总结

    js中this指向问题一直是个坑,之前一直是懵懵懂懂的,大概知道一点,但一直不知道各种情况下指向有什么区别,今天亲自动手测试了下this的指向. 1.在对象中的this对象中的this指向我们创建的对 ...

  4. JS中childNodes深入学习

    原文:JS中childNodes深入学习 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <ti ...

  5. 关于js中this指向的理解总结!

    关于js中this指向的理解! this是什么?定义:this是包含它的函数作为方法被调用时所属的对象. 首先,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁 ...

  6. js中this指向的三种情况

    js中this指向的几种情况一.全局作用域或者普通函数自执行中this指向全局对象window,普通函数的自执行会进行预编译,然后预编译this的指向是window //全局作用域 console.l ...

  7. JS中this指向的更改

    JS中this指向的更改 JavaScript 中 this 的指向问题 前面已经总结过,但在实际开中, 很多场景都需要改变 this 的指向. 现在我们讨论更改 this 指向的问题. call更改 ...

  8. 如何理解JS中this指向的问题

    首先,用一句话解释this,就是:指向执行当前函数的对象. 当前执行,理解一下,也就是说this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定.this到底指向谁?this的最终指向的 ...

  9. 关于js中this指向的问题

    this的绑定规则有4种 默认绑定 隐性绑定 显性绑定 new绑定 this绑定优先级 new 绑定 > 显性绑定 > 隐性绑定 > 默认绑定 1.如果函数被new 修饰 this绑 ...

随机推荐

  1. JDK源码阅读--StringBuilder

    public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, Char ...

  2. mtk 的conferrence call建立流程

    (重点看main_log与) 抓mtk log: 1.*#*#82533284#*#*      进入抓log UI 2.*#*#825364#*#*      进入工程模式 3.进入"Lo ...

  3. 使用RequestsCookieJar自动保存并传递cookie

    使用python的requests开发爬虫程序的时候,经常需要将之前请求返回的cookie值作为下一个请求的cookie进行调用,比如模拟登录之后的返回的sessionID,就是需要作为后续请求的co ...

  4. Spring Boot Starter自定义实现三步曲

    实现自定义的spring boot starter,只需要三步: 1.一个Bean 2.一个自动配置类 3.一个META-INF/spring.factories配置文件 下面用代码演示这三步. 项目 ...

  5. css3之背景background-origin,background-clip,background-size

    background-origin属性指定了背景图像的位置区域. content-box, padding-box,和 border-box区域内可以放置背景图像. background-clip用来 ...

  6. FPFH+ICP点云配准

    A, UniformSampling降噪 B, ISS计算关键点, FPFH特征 在FeatureCloud::setInputCloud中读入点云,并调用processInput进行处理: proc ...

  7. C++面向对象高级编程(下)第一周-Geekband

    勿在浮沙筑高台 革命尚未成功,同志仍需努力 <h1> Conversion Function</h1> class Fraction { public: Fraction(in ...

  8. Redis集群搭建详细过程整理备忘

    三.安装配置 1.环境 使用2台centos服务器,每台机器上部署3个实例,集群为三个主节点与三个从节点: 192.168.5.144:6380 192.168.5.144:6381 192.168. ...

  9. 关于CoCreateInstance的0x800401f0问题

    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&g_pGr ...

  10. mac版pycharm的字体和行间距设置