this到底指向谁,估计很多人在使用javascript的过程中都遇到过,这个关键字如果没搞懂,在一些高级功能中都会困难重重,搜了下相关文章,介绍的都挺多的,也有很深入的,比如汤姆大叔的《深入理解javascript系列》文章。看到很多文章中提到一句话:"this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁实际上this的最终指向的是那个调用它的对象"。

《javascript设计模式与实践》中是这样说的:javascript的this总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境

除去不常用的with和eval,实际应用中,this的指向大致分为下面4种情况:

1、作为对象的方法调用。

2、作为普通函数调用。

3、构造器函数调用。

4、call和apply调用。

情况1:作为对象的方法调用

当函数作为对象的方法调用时,this指向该对象。这是最常见的,比如:

var obj={
a:1,
fun:function(){
console.log(this.a);//输出:1
}
};
obj.fun();

情况2:作为普通函数调用

当函数不作为对象的属性调用时,即作为普通函数调用,this总是指向全局对象。

var a=1;
function fun(){
var a=2;
console.log(this.a);//输出:1
 console.log(a);//输出:2
}
fun();

再看一种情况:

var name="张三";
var obj={
name:"李四",
getName:function(){
console.log(this.name);
}
}
obj.getName();//输出:李四
var getName=obj.getName;
getName();//输出:张三

 直接调用obj.getName(),这里的this是作为对象的方法调用,所以它指向obj,this.name就是李四;

obj.getName赋值给getName后,getName就变成了普通函数,所以指向的是全局的window.name,结果是张三;

举个在实际开发过程中遇到的会让人困惑的例子:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<button id="btn">点我</button>
<script type="text/javascript">
var id="window";
document.getElementById("btn").onclick=function(){
alert(this.id);//输出:btn
var callback=function(){
alert(this.id);//输出:window
}
callback();
}
</script>
</body>
</html>

  点击按钮的时候this指向的是按钮,但是callback是作为普通函数调用的,里面的this指向的是全局对象window,所以结果是window。

此时我们可以临时用一个变量保存对当前对象的引用:

var id="window";
document.getElementById("btn").onclick=function(){
var self=this;
var callback=function(){
alert(self.id);//输出:btn
}
callback();
}

情况3:构造器中调用

function myClass(){
this.name="张三";
}
var child=new myClass();
console.log(child.name);//输出:张三

大部分的javascript函数都可以当做构造函数来使用,构造器函数外表跟普通函数一模一样,区别在于调用的方式。当使用new运算符调用函数时,该函数总会返回一个对象,就是我们常说的实例对象。通常情况下,通过new运算符后,构造器函数中的this就指向的实例对象。

注意:如果构造器函数显式的返回了一个object类型的休息,那么运算结果最终会返回这个对象,而不是上面所期望的。例如:

function myClass(){
this.name="张三";
return {
name:"李四"
}
}
var child=new myClass();
console.log(child.name);//输出:"李四"
console.log(child);//输出:[object Object] {name: "李四"}

  

 这个例子与上面的例子差别就在于构造器函数最后返回了一个对象。如果构造器函数不显式的返回任何数据,或者返回一个非对象类型的数据,就不会出现这种情况,例如:

function myClass(){
this.name="张三";
return "李四"
}
var child=new myClass();
console.log(child.name);//输出:张三
console.log(child);//输出:[object Object] {name: "张三"}

情况4:call和apply

call和apply能够动态的修改传入函数的this:

var obj1={
name:"张三",
getName:function(){
console.log(this.name);
}
};
var obj2={
name:"李四"
};
obj1.getName();//输出:"张三"
obj1.getName.call(obj2);//输出:"李四"
obj1.getName.apply(obj2);//输出:"李四"

  

call和apply的作用这里就不详细说了。

javascript中让你捉摸不定的this的更多相关文章

  1. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  2. javascript中的this与函数讲解

    前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...

  3. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

  4. javascript中的操作符详解1

    好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...

  5. 掌握javascript中的最基础数据结构-----数组

    这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...

  6. javascript中变量提升的理解

    网上找了两个经典的例子 var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); // 10 var ...

  7. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  8. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  9. Javascript中的valueOf与toString

    基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...

随机推荐

  1. robot framework 测试/预发/线上环境快捷切换

    通常情况下布署的三套环境:测试.预发及线上环境.调试或者辅助验证测试时,切环境改变量甚是麻烦.这些变量包括但不限于:一些url信息,数据库信息,预置用户信息等. 切换环境方法一:使用变量文件,通过判断 ...

  2. 【css】——三种方法实现多列等高

    html: <section> <div class="item"> Lorem, ipsum dolor sit <div class=" ...

  3. Swift 里字符串(四)large sting

    对于普通的字符串,对应的_StringObject 有两个存储属性: _countAndFlagsBits: UInt64 _object: Builtin.BridgeObject _countAn ...

  4. centos7在分区上建立文件系统和挂载

    在上一篇博客中,我们只说了硬盘的分区,既然进行分区,那么我们就要知道如何使用这些分区,就是接下来的建立文件系统和挂载. mkfs(make filesystem)格式化,建立文件系统 可以看到各种文件 ...

  5. android Service 学习总结

    学习android开发已经四五个月,由于项目中职责的原因一直没有接触过Service的实际项目,今天重新学一遍Service用法. 问题: 作为四大组件,为什么需要Service? 它与Thread又 ...

  6. jboss8+EJB3+MDB Queue

    1)在使用jboss8即WildFly进行MDB的试验时首先要在jboss8中配置jms 队列. 我使用的是修改配置文件的方式配置Jms Queue队列. 进入jboss8 安装目录的standalo ...

  7. java内存数据管理

    准确的说应该是java8以前的内存管理方式 区别在永久代(方法区)上 public class RamManager { //1.a存储于永久代 public static int a =1; pri ...

  8. Windows下PATH等环境变量详解

    在学习JAVA的过程中,涉及到多个环境变量(environment variable)的概念,如PATH.正确地配置这些环境变量,是能够顺利学习.开发的前提.而经常出现的问题是:有的学习者能够按照提示 ...

  9. SpringMVC访问WEB-INF下的jsp的方法

    当输入localhost:8080/项目名 浏览器弹出不知道神马错误 The absolute uri: http://java.sun.com/jsp/jstl/core cannot be res ...

  10. android学习-Activity和Service的生命周期

    详细请跳转原网页Activity和Service的生命周期(图) 不解释,不懂算我输 Activity的生命周期(图) Service的声明周期