前言

JavaScript中this变量是一个令人难以摸清的关键字,当初学习javascript的时候被这个this指向问题折腾的我是惨不忍睹,漏洞百出。一度想在后面的代码过程中放弃对this的使用,但是this在javascript当中用处太广泛了。

充分了解this的相关知识有助于我们在编写面向对象的JavaScript程序时能够游刃有余,没办法只能硬着头皮上呀。被虐多次再结合自己查阅相关文档资料,总算有一点小小心得。特分享出来,供大家参考!

this简述

关于this的清this所引用的对象到底是哪一个,也许很多资料上都有自己的解释。例如我钟爱的《高三》对this也是简单几页翻过。最后翻阅到MDN上面的wen技术文档,上面解释深得我意。

在绝大多数情况下,函数的调用方式决定了this的值。this不能在执行期间被赋值,在每次函数被调用时this的值也可能会不同。

--MDN社区web技术文档

由此可以推出this的在不同的情况下,this的指向各不相同。简单来说就分为5种情况

1、全局环境

var a = "先制定一个小目标,下一顿饭加一个鸡腿";
console.log(this); // 这里this就指向 window
console.log(this.a); //控制台输出 "先制定一个小目标,下一顿饭加一个鸡腿"

这一种情况相信大家都非常好理解,在全局环境当中this默认是指向window

2、函数中调用

function foo1() {
function bar() {
console.log(this);
}
bar();
}
foo1(); // 输出window

当foo1()执行的时候 ,间接相当于window.foo1()执行函数中的this是指向window,因此控制台相应输出window结果。(foo1() 间接也等于 window.foo1(),这样就是相当于window在调用这个函数,因此this也是指向于window。)

3、对象中调用

var x = "今天交房租";
var obj = {
foo:function() {
console.log(this.x);
},
x:"房租减免";
};
obj.foo(); //控制台输出 "房租减免"

这是当对象obj调用foo()函数,this指向了这个调用对象,即this就等于obj,控制台式输出就变成了obj.最后控制台便输出 "房租减免",唉!!这要是从房东嘴巴里面输出该多好!!

4、构造函数中

var name = "hahaha";
function Obj() {
this.name = "CheDabang";
}
var person = new Obj();
console.log(person.name); //输出 CheDabang

这里通过new运算符创建一个 Obj的对象实例。

变成person{this.name},因此这里this的指向也随着指向这个新实例对象。因此控制台输出 CheDabang

5、apply、call中调用

当一个函数的函数体中使用了this关键字时,通过所有函数都从Function对象的原型中继承的call()方法和apply()方法调用的时候,它的值可以绑定到一个指定的对象上。

function add(c, d){
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
console.log(add.call(o, 5, 7)); //1 + 3 + 5 + 7 = 16
console.log(add.apply(o, [10, 20])); // 1 + 3 + 10 + 20 = 34

小练习

以上就是我们常常出现的5种情况,看到这么多情况的介绍。诸位看官,也晕了吧。不要着急,让我们再来几个小练习感受一下这位this大爷的指向。

题目①
Code
var a = 10;
function test(){
a = 5;
console.log(a);
console.log(this.a);
var a ;
console.log(this.a);
console.log(a);
}
test();
new test();

当调用test()的时候,控制台分别输出 5、10、10、5

当调用 new test()的时候,控制台分别输出 5、undefined、undefined、5

解析

var a = 10 ==> var window.a = 10 ;

当test()调用的时候,间接也相当于window.test()调用。因此当这个函数执行的时候,这里面的this指向的是window对象,因此this.a 指向的是window = 10;

当new test() 实例化,因此this指向的是这个实例的对象,因此这个新对象的a,并没有直接定义过。所以控制台输出undefined

题目②

Code
var Funllname = "john Doe";
var obj = {
Funllname:"Colin Thrig",
prop:{
getFullname:function(){
return this.Funllname;
}
},
};
console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
console.log(test());

控制台输出

undefined

john Doe

解析

控制台结果1:当obj.prop.getFullname()在调用的时候,相当于执行了其中的函数。而由于调用这个函数的是obj.prop调用的,因此this就直接指向obj.prop,但是obj.prop这个对象当中并没有定义Fullname,因此输出undefined

控制台结果2:当var test = obj.prop.getFullname; 这个时候就间接相当于==>var test = function(){return this.Funllname;}

因此当test()调用的时候,就相当于 ==> window.test();,因此其中的this便指向了window对象,所以便输出了 john Doe

题目③
Code
var sex = "male";
var saySex = {
sex:"female",
saySex:function(){
function getSex(){
console.log("this.sex="+this.sex);
}
getSex();
}
}
saySex.saySex();

控制台输出

this.sex = male

解析

控制台结果:当saySex.saySex()调用的时候,只是相当saySex的函数被调用。之后在函数中,函数getSex()被调用,此时this便指向getSex().而函数getSex()默认情况下是指向window的,因此这里输出this.sex = male

题目④

Code
var name = "chedabang";
function sayName(){
var a = {
name:"加一个鸡腿",
sayName:getName
}; function getName(){
console.log(this.name);
} getName();
a.sayName();
getName.call(a);
}
sayName();

控制台输出

chedabang

加一个鸡腿

加一个鸡腿

解析

当sayName()运行的时候时候,先是里面的第一个函数运行,getName().因此因此其中的this,便默认指向了window,因此this.name ==> chedabang

其次a.sayName()运行,因为sayName = getName。所以即当于getName再次被调用,由于存在调用对象a。因此此时this又重新指向对象a,对象 a 当中存在name属性,因此输出加一个鸡腿

最后 getName.call(a).运行的时候,将对象a给绑定到上面,因此函数里面的this就不指向window,而指向的是绑定的对象a,因此输出 加一个鸡腿

题目⑤

Code
var a = {
name:"张三",
sayName:function(){
console.log("this.name="+this.name);
}
};
var name = "李四";
function sayName1(){
var sss = a.sayName;
sss();
a.sayName();
(a.sayName)();
(b = a.sayName)();
}
sayName1();

控制台输出:

this.name=李四

this.name=张三

this.name=张三

this.name=李四

解析

当sayName1()运行的时候,sayName1函数内部首先是

控制台结果1:var sss = a.sayName ==> var sss = function(){console.log("this.name="+=this.name);} 像前面我们总结的一样函数中调用,因此这里的this指向window对象,因此输出this.name=李四

控制台结果2:a.sayName();这里a直接调用其中的匿名函数,因此此时this指向a,因此a.name = "张三",所有控制台输出this.name=张三

控制台结果3:这里(a.sayName)();其实间接相当于 == a.sayName();这里指的是值立即执行。不管如何始终是对象a在调用sayName这个函数。因此控制台也就跟着一起输出this.name=张三

控制台结果4:和控制台结果3一样,代表变量b立即执行,而b和控制台结果1中sss一样,也属于函数中调用,因此this这里指向window。即控制台输出this.name=李四

看到这里是不是豁然开朗了,相信进过this这么几道题的磨练,大家应该对this了解有加深了不少。如果讲的有错误,还请大牛们给指出来,在此谢谢了.

浅谈javascript-this关键字的更多相关文章

  1. 浅谈 JavaScript 编程语言的编码规范

    对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编 ...

  2. 浅谈JavaScript中的null和undefined

    浅谈JavaScript中的null和undefined null null是JavaScript中的关键字,表示一个特殊值,常用来描述"空值". 对null进行typeof类型运 ...

  3. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  4. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  5. 浅谈JavaScript浮点数及其运算

    原文:浅谈JavaScript浮点数及其运算     JavaScript 只有一种数字类型 Number,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的.浮点数的精度问题 ...

  6. 浅谈javascript的原型及原型链

    浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下: prototype属性 [[prototype]] __proto__ prototype属性 只要创建了一个函数,就会为 ...

  7. 浅谈JavaScript中的正则表达式(适用初学者观看)

    浅谈JavaScript中的正则表达式 1.什么是正则表达式(RegExp)? 官方定义: 正则表达式是一种特殊的字符串模式,用于匹配一组字符串,就好比用模具做产品,而正则就是这个模具,定义一种规则去 ...

  8. [转载]浅谈JavaScript函数重载

     原文地址:浅谈JavaScript函数重载 作者:ChessZhang 上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试).面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都 ...

  9. 浅谈JavaScript中的内存管理

    一门语言的内存存储方式是我们学习他必须要了解的,接下来让我浅谈一下自己对他的认识. 首先说,JavaScript中的变量包含两种两种类型: 1)值类型或基本类型:undefined.null.numb ...

  10. 【javascript】浅谈javaScript的深拷贝

        前言: 最开始意识到深拷贝的重要性是在我使用redux的时候(react + redux), redux的机制要求在reducer中必须返回一个新的对象,而不能对原来的对象做改动,事实上,当时 ...

随机推荐

  1. 20175316盛茂淞 2018-2019-2《Java程序设计》结对编程项目-四则运算 第二周(6)

    20175316与20175329 结对编程练习_四则运算(第二周) 1.需求分析 实现一个命令行程序,要求: 自动生成指定数量的小学四则运算题目(加.减.乘.除) 支持整数 统计正确率 支持多运算符 ...

  2. 《Linux就该这么学》第十四天课程

    samba服务的配置文件解读 samba服务解决了Linux系统与Windows系统之间的文件共享问题,是一个非常不错的服务 原创地址:https://www.linuxprobe.com/chapt ...

  3. 2019浙江省赛B zoj4101 Element Swapping(推公式)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6003 题意 \(数组a通过交换一对数字,得到了b数组,给出x=\sum^n_{ ...

  4. python模块:logging

    # Copyright 2001-2016 by Vinay Sajip. All Rights Reserved. # # Permission to use, copy, modify, and ...

  5. 神经网络参数与TensorFlow变量

    在TensorFlow中变量的作用是保存和更新神经网络中的参数,需要给变量指定初始值,如下声明一个2x3矩阵变量 weights =tf.Variable(tf.random_normal([2,3] ...

  6. 2018-04-10 我的GitHub诞生的日子,欢迎大家吐槽批评

    我的GitHub,诞生的日子,欢迎大家吐槽与批评,嘻嘻 首先是自己想刷一下LeetCode上的代码,其次创建了自己的读书笔记以及面试经验与教训 下边是仓库的Git链接,欢迎大家的批评与修正,谢谢: L ...

  7. 第二次scrum

    scrum说明 在第一次已有的基础上,进行了具体的实现.完成了具体的界面设计,还有各个栏目,如:发帖,搜索,禁言等. 类图 依次是外观模式图,发帖图,禁言图. 外观模式图 发帖图 禁言图 团队成员 潘 ...

  8. How to setup Visual Studio without pain

    Visual Studio (VS) can be very hard to install. If you are lucky, one whole day may be enough to ins ...

  9. SolrCloud的搭建与稳定性测试

    转载请注明出处:http://www.cnblogs.com/wubdut/p/7573738.html 一.集群搭建 1. zookeeper搭建(版本:3.4) 1.1 zoo.cfg配置文件: ...

  10. 28.TreeSet

    与HashSet是基于HashMap实现一样,TreeSet同样是基于TreeMap实现的.在前一篇中详细讲解了TreeMap实现机制,如果客官详细看了这篇博文或者对TreeMap有比较详细的了解,那 ...