前言

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. Java集合类的底层实现探索

    List: ArrayList 首先我们来看看jdk的ArrayList的add方法的源码是如何实现的: public boolean add(E e) { ensureCapacityInterna ...

  2. BERT(Bidirectional Encoder Representations from Transformers)

    BERT的新语言表示模型,它代表Transformer的双向编码器表示.与最近的其他语言表示模型不同,BERT旨在通过联合调节所有层中的上下文来预先训练深度双向表示.因此,预训练的BERT表示可以通过 ...

  3. 查看进程被哪台电脑的哪个进程连接(netstat)

    1.netstat -ano|findstr 进程号,找出连接该进程A所有的ip(可以看到该进程的端口号和连接进程的端口号): 2.到连接该进程的电脑上,打开cmd命令行,输入netstat -ano ...

  4. (26)A delightful way to teach kids about computers

    https://www.ted.com/talks/linda_liukas_a_delightful_way_to_teach_kids_about_computers/transcript00:1 ...

  5. temp--贵州银行

    -------住宿----泊乐酒店----8905----与朱聿一起住 2018年  1月3日晚 1月4日晚  1月5日晚 1月6日晚  1月7日晚 1月8日晚  1月9日晚 已结清! ======= ...

  6. XSSearch 说明文档保存

    XSSearch All Packages | 属性 | 方法(函数) 包 XS 继承关系 class XSSearch » XSServer » XSComponent 版本 1.0.0 源代码 s ...

  7. 关于select的使用感受~大坑~select不能添加点击事件触发~

    这是一个坑,把我摔惨了! select+option是浏览器自带的下拉选项框,样式及其丑,还好现在有很多框架都相应做了些美化,select 元素是一种表单控件,可用于在表单中接受用户输入. 还有一个重 ...

  8. windows putty xming virt-manager

    记一次windows环境使用linux下使用virt-manager软件的问题 环境:windows server 2008.ubuntu-server 软件:putty.virt-manager.x ...

  9. 安装MySQL5.7.19 网上的文章参考 并做了部分修改

    1,从官方网址下载MySQL5.7.19源码包 http://dev.MySQL.com/downloads/mysql/#downloads     2,安装好CentOS6.7 64位操作系统. ...

  10. python的基本数据类型(一)

    一.运算符逻辑运算and:两边都真则真or:有真则真not:非假是真 顺序:()>==>not==>and>=or 二.while.. elsewhile 条件: 代码块els ...