javascript中的this学习起来相对复杂,最近花了点时间研究,总结起来大概这只有5种情况,相信只要熟悉这5种用法,基本是可以解决所有的this问题,文本不介绍this设计原理,只介绍用法,阅读本文,你需要了解javascript执行上下文环境,博主写这种文章的目的,主要还是给自己做下笔记,后续也会输出javascript的学习笔记。

全局代码中的this & 调用普通函数中的this & this作为对象的属性值

全局代码中的this ,永远是window。

  1. //全局环境下,this永远是window。
  2. console.info(this === window);// true
  3.  
  4. //定义全局对象的属性
  5. this.cat = '猫'; // global.cat = '猫'
  6. console.info(cat); // 猫
  7.  
  8. //给一个无标示符变量赋值
  9. dog = '狗';
  10. console.info(this.dog); // '狗'
  11.  
  12. //通过变量声明
  13. var bird = '鸟';
  14. console.info(this.bird); // '鸟'

调用普通函数中的this,永远是window。

  1. function fn1() {
  2. this.cat = '包子'
  3. console.info(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
  4. console.info(this.cat);//包子
  5. }
  6. fn1()

this作为对象的属性值,永远是window。

  1. let obj = {
  2. cat : '猫宝宝',
  3. cat_father : this,
  4. cat_self : this.cat
  5. }
  6. console.info(obj.cat_father);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
  7. console.info(obj.cat_self);//undefined

其它注意:任何时候不能改变this的值。

  1. //报错,任何时候不能改变this的值
  2. this = '鸟'

构造函数中this

函数作为构造函数用,那么其中的this就代表它即将new出来的对象。

  1. function Fn2() {
  2. this.cat = '包子',
  3. this.dog = '饺子'
  4. console.info(this);//Fn2 {cat: "包子", dog: "饺子"}
  5. }
  6. let fn2 = new Fn2();
  7. console.info(fn2.cat);//包子
  8. console.info(fn2.dog);//饺子

原型链中this

在构造函数的prototype中,this代表函数即将new出来的对象。

  1. function Fn3() {
  2. this.cat = '包子'
  3. }
  4. Fn3.prototype.getItem = function(){
  5. return this.cat;
  6. }
  7. let fn3 = new Fn3();
  8. console.info(fn3.getItem());//包子

其实,不仅仅是构造函数的prototype,即便是在整个原型链中,this代表的也都是当前对象的值。

函数作为对象的一个属性被调用

函数作为对象的一个属性被调用,函数中的this指向调用它的对象,加深红色的这句话非常关键。

  1. let obj = {
  2. cat : '猫宝宝',
  3. fn : function(){
  4. console.info(this === obj);//true
  5. console.info(this.cat);//猫宝宝
  6. }
  7. }
  8. obj.fn()

又如小程序中,使用Page(Object) 函数用来注册一个页面,接受一个 Object 类型参数,那么this指向该Object

  1. Page({
  2. data: {
  3. version: '1.0.1',
  4. cat:'张老板他妹'
  5. },
  6. onLoad: function () {
  7. console.info(this.data);//{version: "1.0.1", cat: "张老板他妹"}
  8. }
  9. })

在函数中this到底取何值,是在函数真正被调用执行的时候确定的,函数定义的时候确定不了。因为this的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境,但最终函数中的this指向调用它的对象

  1. let obj = {
  2. cat: '大猫',
  3. fn: function () {
  4. console.info(this.cat)
  5. }
  6. };
  7. //fn函数作为obj对象的一个属性被调用,在obj环境中执行,函数中的this指向该对象
  8. obj.fn() // 大猫
  9.  
  10. var fn_new = obj.fn;
  11. var cat = '小猫';//全局环境的cat
  12.  
  13. //fn函数赋值给变量fn_new的时候并没有执行,此时this指向window,那么执行fn_new()时,this.cat对应取值为window.cat
  14. fn_new() // 小猫

再来一个例子,对象的中嵌套子对象,子对象的属性值为函数,函数被子对象调用,那么函数中的this指向子对象,也就是函数中的this指向调用它的对象

  1. let obj = {
  2. cat: '大猫',
  3. obj_in: {
  4. fn: function () {
  5. console.info(this.cat) //undefined
  6. }
  7. }
  8. }
  9. //fn函数是被obj_in对象所调用,所以this指向的也obj_in对象
  10. obj.obj_in.fn();

最后一个例子,对象的属性为函数,函数中嵌套函数,this放在嵌套函数中的情况

  1. let obj = {
  2. cat : '猫',
  3. fn : function(){
  4. function fn_in(){
  5. console.info(this);//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
  6. console.info(this.cat);//undefined
  7. }
  8. //执行fn函数后,嵌套函数fn_in在fn环境中执行,回到文章中说的第一种情况,此时fn_in是普通函数,则它的this指向window
  9. fn_in();
  10. }
  11. }
  12. obj.fn()

函数用call或apply或bind调用

当一个函数被call和apply调用时,this的值就取传入的对象的值。

  1. let obj1 = {
  2. baobao : '猫'
  3. }
  4. let obj2 = {
  5. baobao : '羊'
  6. }
  7. let obj3 = {
  8. baobao : '鹅'
  9. }
  10. let fn3 = function(){
  11. console.info(this.baobao);
  12. }
  13. fn3.apply(obj1);//猫
  14. fn3.call(obj2);//羊
  15. fn3.bind(obj3)();//鹅

同函数作为对象的一个属性被调用一样,函数fn4_in是在obj.fn4内部定义的,所以它仍然是一个普通的函数,this仍然指向window。

  1. let obj3 = {
  2. baobao : '猫'
  3. }
  4. let fn4 = function(){
  5. function fn4_in(){
  6. console.info(this.baobao);//undefined
  7. }
  8. fn4_in()
  9. }
  10. fn4.apply(obj3);

参考资料

http://www.ruanyifeng.com/blog/2018/06/javascript-this.html

http://www.cnblogs.com/TomXu/archive/2012/01/17/2310479.html

http://www.cnblogs.com/wangfupeng1988/p/3988422.html

【原】javascript笔记之this用法的更多相关文章

  1. 【原】javascript笔记之Array方法forEach&map&filter&some&every&reduce&reduceRight

    做前端有多年了,看过不少技术文章,学了新的技术,但更新迭代快的大前端,庞大的知识库,很多学过就忘记了,特别在项目紧急的条件下,哪怕心中隐隐约约有学过一个方法,但会下意识的使用旧的方法去解决,多年前ES ...

  2. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  3. jQuery学习笔记之Ajax用法详解

    这篇文章主要介绍了jQuery学习笔记之Ajax用法,结合实例形式较为详细的分析总结了jQuery中ajax的相关使用技巧,包括ajax请求.载入.处理.传递等,需要的朋友可以参考下 本文实例讲述了j ...

  4. javascript confirm()函数的用法

    javascript confirm()函数的用法 confirm():确认消息对话框.用于允许用户做选择的动作.弹出的对话框中包含一确定按钮和一取消按钮. confirm(str) 参数说明: st ...

  5. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  6. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  7. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  8. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  9. javascript中的继承用法

    本文实例汇总了javascript关于继承的用法,希望本文所述对大家的javascript程序设计有所帮助.分享给大家供大家参考.具体如下:代码如下: /** * 实现子类继承父类,但不会产生多余的属 ...

随机推荐

  1. Flask入门之SQLAlchemy数据库连接操作(第15讲)

    一.库安装 Flask-SQLAlchemy 2 SQLAlchemy 1.0.8 二.进入venv 三.切换到项目Sample\ 文件夹,进入manager.py 的shell python man ...

  2. 用shell处理以下内容 1、按单词出现频率降序排序! 2、按字母出现频率降序排序! the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support

    此题目有多种解法,sed.awk.tr等等,都可以解决此题,命令运用灵活多变. 编写shell脚本no_20.sh 解法1: #!/bin/bash ###-------------CopyRight ...

  3. DX11 Without DirectX SDK--01 DirectX11初始化

    回到 DirectX11--使用Windows SDK来进行开发 由于个人觉得龙书里面第4章提供的Direct3D 初始化项目封装得比较好,而且DirectX SDK Samples里面的初始化程序过 ...

  4. python识别图片文字

    因为学校要求要刷一门叫<包装世界>的网课,而课程里有200多道选择题,而且只能在手机完成,网页版无法做题,而看视频是不可能看视频的,这辈子都不可能看...所以写了几行代码来进行百度搜答案. ...

  5. 微信小游戏开发Canvas资源汇总

    Demo: 微信小程序demo组件:股票分时图 微信小程序小组件:仿直播点赞气泡效果,基于Canvas 优质demo推荐:二维码生成器:使用canvas与纯JS版二维码生成 微信小程序学习用完整dem ...

  6. 深入理解Java NIO

    初识NIO: 在 JDK 1. 4 中 新 加入 了 NIO( New Input/ Output) 类, 引入了一种基于通道和缓冲区的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存 ...

  7. linux netlink通信机制

    一.什么是Netlink通信机制  Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口. Netlink 是一种特殊的 s ...

  8. 推荐一个比crontab更好用的东西:crongo

    This is a crontab service that supports hot plug and high performance. In addition, it supports seco ...

  9. Windows上使用Thunderbird与GPG发送和解密公钥加密的电子邮件

    作者:荒原之梦 原文链接:http://zhaokaifeng.com/?p=552 非对称加密的原理: 最先出现的加密方法是对称加密.在对称加密算法中是不区分公钥和私钥的,加密与解密使用的都是同一个 ...

  10. postman的安装与使用(模拟请求)

    最近需要测试产品中的REST API,无意中发现了PostMan这个chrome插件,把玩了一下,发现postman秉承了一贯以来google工具强大,易用的特质.独乐乐不如众乐乐,特此共享出来给大伙 ...