Javascript:this用法

#Javascript:this用法整理
pingan 于 星期三, 18/12/2013 - 22:32 提交

常用Javascript的人都知道,[this这个关键字在一个函式内究竟指向谁]的这个问题很令人头大,本人在这裡整理了一下Javascript中this的指向的五种不同情况,其中前三种属于基本的情况,而后两种情况可基于前三种情况的方式来进行思考。

1.this指向于调用该函式之物件
如果你有学过C/C++,你可能会记得一个物件内的成员函式裡的this指的即是该成员函式所在之物件,但在Javascript裡则有那麽些许不同,Javascript裡的this看的是究竟是谁调用该函式,而不是看该函式被定义在哪个物件内,这个大原则抓到了,基本上就已经可以探知this的奥秘了。底下写一下这种情况的公式与范例:

公式

 1 物件.函式(); //函式内的this指向该物件
范例

var obj = {
  x: 20,
  f: function(){ console.log(this.x); }
};

obj.f(); //由于调用f函式时,点前面物件为obj,故f内的this指向obj,则输出为20。

obj.innerobj = {
  x: 30,
  f: function(){ console.log(this.x); }
}

obj.innerobj.f(); //由于调用f函式时,点前面物件为obj.innerobj,故f内的this指向obj.innerobj,则输出为30。

2.this指向全域物件(浏览器:window物件、node.js:GLOBAL物件)
如果调用函式的前方并未有物件,则函式内this就指向全域物件。在浏览器内全域物件为window物件,而在node.js中全域物件则为GLOBAL物件。底下一样写一下这种情况的公式与范例:

公式


 函式(); //函式内的this指向全域物件
范例

var x = 10;
var f = function(){
  console.log(this.x);
};

f(); //由于调用f函式时,前方并未有[物件.]的形式,故f内的this指向全域物件,则输出全域变数的x(10)。
例外:在使用node.js时,若使用node file.js这样的方式执行js档,并不会让宣告的全域变数挂在全域物件上(意指会利用function将code整个包起来执行),故输出应为undefined。
前两种情况常见误导范例
范例一、物件之成员函式内有函式(感谢NSLin在实务读书会上的范例Code)
example1.js


var x = 10;
var obj = {
  x: 20,
  f: function(){
    console.log(this.x);
    var foo = function(){ console.log(this.x); }
    foo(); // (2)
  }
};

obj.f(); // (1)
这个范例会输出多少呢?别忘记大原则,在Javascript裡的this看的是究竟是谁调用该函式,故并不会输出20 20,而是输出20 10,为什麽呢?因为(1)obj.f()调用时,f前面物件为obj,故f内的this指向obj。但因为调用f内的(2)foo函式时是用foo(),调用的前方并未有物件,故foo内的this指向全域物件,所以输出会是全域变数的x的值。

若要让foo内使用obj.x的值,解法如下:

example1.js


var x = 10;
var obj = {
  x: 20,
  f: function(){
    console.log(this.x);
    var that = this; //使用that保留在这个函式内的this
    var foo = function(){ console.log(that.x); } //使用that取得obj
    foo();
  }
};

obj.f();
范例二、借用函式
example2.js


var x = 10;
var obj = {
  x: 20,
  f: function(){ console.log(this.x); }
};

obj.f(); // (1)

var fOut = obj.f;
fOut(); //(2)

var obj2 = {
  x: 30,
  f: obj.f
}

obj2.f(); // (3)
范例中三次调用之函式的this所指向的物件为何,不知道各位能不能看得出来。虽然用的是同一个函式,但是因为调用的不同,故this所指向的物件就不同。(1)obj.f()的f所指向的是obj,这比较没有问题,输出的会是20;而(2)fOut()裡的this,则是因为调用时前方无物件,则this所指的是全域物件,输出的会是10;最后(3)obj2.f()则是obj2去呼叫f,故f内的this指向的是obj2,输出的会是30。

3.this指向利用call或apply所指派给this的物件
有个方法可以更改前两种叙述中this指派的值,就是利用call与apply。call与apply都是呼叫该函式并让该函式的this指向给予call或apply的第一个参数。至于call和apply的差别则是在于其后面给予被调用之函式的参数放入的方法不同,一个是直接摊平放在第二个以后的参数;一个是直接放入一个裡面放要给予之参数的阵列。底下一样看一下公式和范例:

公式

(A物件.)函式.call(B物件,参数1,参数2,参数3, ......); //函式的this指向B物件(若B物件为null,则指向全域物件)
(A物件.)函式.apply(B物件,[参数1,参数2,参数3, ......]); //函式的this指向B物件(若B物件为null,则指向全域物件)
范例

var obj = {
  x: 20;
  f: function(){ console.log(this.x); }
};

var obj2 = {
  x: 30;
};

obj1.f.call(obj2); //利用call指派f的this为指向obj2,故输出为30
4.this指向new所产生之新物件
若将函式当作建构式(constructor)来用,则内部的this则指向于new所产生之新物件。

公式

new 建构式(); //建构式内之this指向new所产生之新物件
范例

function Monster(){
  this.hp = 100;
};

var monster = new Monster(); //Monster的this指向new出来之新物件并回传回来,new的写法就类似于下面的写法。
var monster = (function(){
  var _new = {

    constructor: Monster,

     __proto__: Monster.prototype

  }; //在IE内可能不相似
  _new.constructor(); //这也是为何说可以利用前三种情况来变化的原因,constructor呼叫时,this指向的即是_new这个物件。
  return _new;
})();
5.callback函式内的this会指向于调用放入该callback的函式之this所指向之物件
先想想在jQuery中,我们若要让#button这个元素被click的时候,内容改为“Clicked”这样的字串,该如何写呢?

clicked.js


$('#button').click(function(){
  this.html("Clicked");
})
此时这个this居然会指向$(‘#button’)这个物件,感觉很自然,但实际想想会觉得很神奇。假设你写一个function,它可以传入一个function,并在里面呼叫传入的function,你该怎么写呢?

function-to-function.js


var f = function(innerf){
  //前面的处理
  innerf(arg1, arg2, arg3, ......);
  //后面的处理
}
但如果这样写的话,innerf里的this根据前述规则就应该是全域物件了!那为什么常常别人实作的callback函式可让this指向于调用放入该callback的函式之this所指向之物件呢?这表示大家实际上会遵守一个规则,会将自己的this传给callback当作它的this来用!这也是为什麽我说这个情况其实也是前三种情况的变化而已了!所以上面的code应该改成如下的形式会比较好:

function-to-function-improved.js


var f = function(innerf){
  //前面的处理
  innerf.call(this, arg1, arg2, arg3, ......);
  //或是innerf.apply(this, [arg1, arg2, arg3, ......])
  //后面的处理
}

转载于:https://www.cnblogs.com/pingan1314/p/javascript_this.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/300453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动画演示男性结扎手术 | 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅流鼻涕了怎么办?医学教育徐琦招聘程序员啦知识萌死大丧失;图熊本科技把下列句子补充完整图三好学生李宇幼年的大象喝水并不会使用鼻子而是趴在水里直接用嘴大喝一顿它们9个月之后才会懂得用鼻子喝水科普斯基请…

MYSQL 只能回环口链接_loopback回环口详解

在配置OSPF路由协议的时候配置回环(loopback)接口是很重要的1件事.Cisco建议你配置OSPF的时候顺便配置回环接口.所谓回环接口,是逻辑接口而非物理接口,即不是你触摸的到的router上的真正的接口.作用是作为诊断OSPF而用.如果router的某一个接口由于故障down掉而不可用了,此时你怎…

AspNetCoreMassTransit Courier实现分布式事务

在之前的一篇博文中,CAP框架可以方便我们实现非实时、异步场景下的最终一致性,而有些用例总是无法避免的需要在实时、同步场景下进行,可以借助Saga事务来解决这一困扰。在一些博文和仓库中也搜寻到了.Net下实现Saga模式的解决方案MassTransit…

可能会紧急用到的Linux命令

查看当前网络连接数: netstat -na|grep ESTABLISHED|awk {print $5}|awk -F: {print $1}|sort|uniq -c|sort -r -n删除掉不以java和xml结尾7天没有使用的文件 : find . ! -name *.java ! -name *.xml -atime 7 -exec rm {} \;转载于:https://blog.51cto.com/guihai…

设置列表字段为主键

转贴:Sample event handler to set a field as a pr imary key (enforce no duplicates) Got this as a request from a reader- how to prevent users from adding items with same titles as ones that already exist in the list. Codeusing System;using System.Collectio…

被学校辞退、拒绝FB后:语音识别大牛Povey确认兼职北京初创公司,称主业还选中国...

全世界只有3.14 % 的人关注了青少年数学之旅由于5月的学生抗议事件,语音识别领域著名学者、原约翰霍普金斯大学教授Daniel Povey被学校辞退。随后,Daniel Povey准备进入Facebook从事语音识别系统的开发,但是由于Facebook要对其进行长达6周的审…

也谈子网划分和子网通信

子网划分和子网通信在小型网络中应用不多,但随着公司规模的扩大,这样的问题就会提上网管的工作计划。资料略加整理,希望对各位有帮助。也谈子网划分和子网通信1.网络IP地址和子网掩码的分类:A类:IP: 0.0.0.0 &#xff…

java io流学设置编码_Java学习日志(21-2-IO流-基本数据类型与字节数组对象与、编码解码)...

操作基本数据类型的流对象DataStream/*可以用于操作基本数据类型数据的流对象*/import java.io.*;class DataStreamDemo{public static void main(String[] args)throws IOException{// writeData();// readData();// writeUTFDemo();// OutputStreamWriter oswnew OutputStrea…

dotnet中的counters说明(二)

上篇说了System.Runtime,它负责应用运行的环境资源的收集,这篇要继续说AspNetCore的Hosting,Http.Connections和Server.Kestrel三个计数器。同时,下面指标各项()里的项目是--counters 参数[]里的项,用逗号分隔多项指标。Microsoft…

Asp组件中级入门与精通系列之五

我们学习来看一下Response对象。其实我们前面的教程中一直都在使用这个对象的Write方法。 这里我们用Response对象设置cookie。 ? 打开vb6,新建Activex Dll工程。工程名修改为fCom,类名修改为fZ5 引用“Microsoft Active Server Pages Object”对象库。 创建两个组件事件&…

有这些好习惯,可以让你悄悄变优秀

全世界只有3.14 %的人关注了青少年数学之旅这是一个普遍无趣的时代,很多人看似忙到起飞内在却空虚迷茫。今天我们为你诚意推荐几个公众号它们会成为你生活的一剂调味料,让你做一个学识丰富、灵魂有趣的人。快来关注,开启精彩的生活吧&#xf…

java设置access-allow_Java Web如何设置多个Access-Control-Allow-Origin

有没有办法让Access-Control-Allow-Origin header允许设置multiple cross-domains呢?如果设置response.addHeader("Access-Control-Allow-Origin","*");感觉这个接口太开放了,不太安全。 我想只设置自己指定的若干个域名或者端口可以…

paip.提升用户体验--提升java的热部署热更新能力

paip.提升用户体验--提升java的热部署热更新能力 想让java做到php那么好的热部署能力 "fix online"/在线修复吗??直接在服务器上修改源码生效,无需重启应用。。作者Attilax 艾龙, EMAIL:1466519819qq.com来源&#x…

夏利车电动窗功能设定

夏利车电动窗功能设定 我车的前有门电动车窗坏了,所以去汽配城购买了电动升降器,准备自己进行更换,修车的要我100元RMB,自己购买配件花了我65省了35元呵呵, 但是自己花了很长时间更换完成之后发现车窗怎么也关不严&…

微软 MS Learn 上线 Blazor 入门教程

微软官方学习网站 MS Learn 上线了 Blazor 入门教程模块,希望通过这个课程,让开发人员了解如何设置开发环境,以及如何使用 Blazor、Visual Studio Code 和 C# 生成你的首个 Web 应用。Build a web app with Blazor - Learndocs.microsoft.com…

Type Casting

Type Casting C : Documents : C Language Tutorial : Type Casting Search: userpass[register] javascript and cookies required C Language TutorialIntroduction?Instructions for useBasics of C?Structure of a program?Variables. Data Types.?Constants?Oper…

世界最牛实验室,堪称诺贝尔奖孵化器!到底是个怎样神奇的存在?!

▲ 点击查看随着诺贝尔各个奖项陆陆续续的公布,卡文迪许实验室,又开始重回大众视野。在这个世界最牛实验室之一的实验室里,仅仅过去了一百多年,就不断涌现出一批又一批世界一流的科学家:把电与磁进行有机统一的麦克斯…

java接口那一节是哪的知识_Java中的接口知识汇总

Java中的接口知识汇总发布于 2020-4-29|复制链接本文给大家汇总介绍了在java中的接口知识,包括为什么要使用接口、什么是接口、抽象类和接口的区别、如何定义接口以及定义接口注意点,希望大家能够喜欢一.为什么要使用接口 假如有一个需求:要求…

用C语言实现解析简单配置文件的小工具

本文介绍作者写的一个小工具,简单的代码中包含了C语言对字符串的处理技巧,对文本文件的简单解析,二进制文件的数据复制的方法,以及格式化输出文本文件的示例。 工具的输入是如下内容的配置文件: [plain] view plaincop…

Delphi应用程序在命令行下带参数执行返回命令行提示的问题

在命令行模式(CMD)下执行时,想获得执行参数,用以下变量: ParamCount:参数个数 ParamStr:为参数数组 如果想在执行完一个操作后在命令行作出相应提示,就应该在相应位置放入…