this

this对于初学 JS 的新人来说,是一道坎,看到this就晕头晕脑,脑容量一下不够用了。

先来说下判断this结论

  1. this是函数调用时call的第一个参数
  2. this只有在函数执行的时候才能被确定,实际指向调用它那个对象(上一级)

先来看下函数常用的几种调用方式

fn(a,b)
fn.name(a,b)
var f = fn.name; f(a,b)
fn.call(undefined,a,b)
fn.apply(undefined,[a,b])

上面三种调用方法对于新人很熟悉,而对后面两种方法比较陌生,自然也就弄不明白this含义了。

改写下函数的调用方式就会发现这两种是等价的,回到上面说的结论,call的第一个参数是thisab才是传进去的参数。

fn(a,b) === fn.call(undefined,a,b) === window.fn.apply(window,[a,b])

明白了这点,大部分的this就不难判断了,新人在判断this时只需改写函数调用方式就能知道this指向了。

this例子

下面方法中暂且不讨论严格模式,this的指向
例子1:

var user = 'window'
function fn(){var user = 'object';console.log(this.user); //windwow
}
fn();    //改写 window.fn.call(window)

fn是全局对象window的方法

例子2:

var user = 'window'
var obj = {user:'object',fn:function(){console.log(this.user);  //object}
}
obj.fn();    //改写 obj.fn.call(obj)

这里的fn是被obj调用的,所以fn内部的this指向obj内部的user

你可能会有疑惑了,这里是不是可以改写成window.obj.fn.call(window),往下看

例子3:

var user = 'window'
var obj = {user:'object',fn:function(){console.log(this.user);  //object}
}
window.obj.fn();    //改写 window.obj.fn.call(window.obj)

先看下面例子

例子4:

var user = 'window'
var obj = {user:'object',fn1:{user:'function',fn2:function(){console.log(this.user)    //function}}
}
obj.fn1.fn2();    //改写 obj.fn1.call(obj.fn1)

例子3中正常情况下都是把window给省略的,这里写出来是为了和例子4做对比。

假设例子4中obj对象是不是window下的方法,而是和window平级(实际不存在这种假设,容易理解)。

这里是链式调用,this的最终指向是调用它的上一层对象fn1,但是不能改写成obj.fn1.call(fn1),只有window可以省略。

例子5:

var user = 'window'
var obj = {user:'object',fn1:{user:'function',fn2:function(){console.log(this.user)    //window}}
}
var a = obj.fn1.fn2;
a()        //改写 window.a.call(window)

先看下面例子

例子6:

var a = {user:'window'}
var obj = {user:'object',fn1:{user:'function',fn2:function(){console.log(this.user)    //window}}
}obj.fn1.fn2.call(a);

看到例子5和例子6是不是已经晕了。

例子5中,var a = obj.fn1.fn2只是赋值,并没用执行,而真正执行的时候,awindow下的方法,所以fn2内部的this指向window下的user

例子6中,call的第一个参数是a,那this肯定指向auser,因为显示绑定优先级高于隐示绑定。

那你可能要问什么是显示绑定,什么是隐示绑定呢?

obj.fn()    //隐示绑定
obj.fn.call(obj)    //显示绑定

也就是说你改写后的调用就是显示绑定。

new构造函数

例子7:

function Fn(){this.user = 'object';
}
var a = new Fn();
console.log(a.user); //object

例子7中,因为构造函数的this指向构造出来的实例,所以a是用new构造出来的对象,那么this就是指向a

构造函数中要注意的一点是:默认情况下,构造函数是没有return,但是非要加一个return的话。

  1. 如果return的是引用类型值,那么构造函数的this就指向return的对象
  2. 如果return的是基本类型值,那么构造函数的this就指向构造出来的实例化函数

this基本应用就是这些,做一些实操练习巩固一下

this实操

实操1:

function X(){return object = {name:'object',f1(x){x.f2()        //② 改写 options.f2.call(options)},f2(){console.log(this)}}
}var options = {name:'options',f1(){},f2(){console.log(this)    //③ 运行这个this,打印 options 函数}
}var x = X();
x.f1(options);    //① 改写 object.f1.call(object,options)

看到this就马上改写,不改写就做,肯定错。

分析

  1. 首先把x.f1(options)改写object.f1.call(object,options)
  2. x.f1(options)调用object对象内部f1方法,把options函数作为参数传入,所以 object内部f1(x)中的xoptions函数
  3. f2内部的this指向options

实操2:

function X(){return object = {name:'object',f1(x){x.f2.call(this)        //② 这里是显示绑定,改写 options.f2.call(object)},f2(){console.log(this)}}
}var options = {name:'options',f1(){},f2(){console.log(this)    //③ 运行这个 this 打印 object}
}var x = X()
x.f1(options)    //① 改写 object.f1.call(object,options)

分析

  1. 首先把x.f1(options)改写object.f1.call(object,options)
  2. f1内部的this指向object
  3. x.f2.call(this)改写options.f2.call(object),这里的.call(this)是显示指定
  4. f2内部的this就是object

实操3:

function X(){return object = {name:'object',options:null,        //③ options = optionsf1(x){this.options = x    //② 改写 object.options = optionsthis.f2()            //③ 改写 object.f2.call(object)},f2(){this.options.f2.call(this)    //④ 显示绑定,改写object.options.f2.call(object)}}
}var options = {name:'options',f1(){},f2(){console.log(this)    //⑤运行这个 this,打印 object}
}var x = X()
x.f1(options)    //① 改写 object.f1.call(object,options)

分析

  1. 首先把x.f1(options) 改写object.f1.call(object,options)
  2. f1内this指向objectoptions作为参数传进来
  3. this.options = x改写object.options = options,同时也把this.f2()改写称object.f2()
  4. this.options.f2.call(this) 改写object.options.f2.call(object),.call(this)是显示绑定
  5. f2内部的this就是object

前端学习笔记之this——懂不懂由你,反正我是懂了相关推荐

  1. 2017-2-15从0开始前端学习笔记(HTML)-图片-表格-表单

    2017-2-15从0开始前端学习笔记-图片-表格-表单 标签 图片 图片<img src="#" alt="文本说明 不能加载图片时显示" title= ...

  2. 前端学习笔记:Bootstrap框架入门

    前端学习笔记:Bootstrap框架入门 一.Bootstrap概述 1.基本信息 ​Bootstrap,来自 Twitter,是目前很受欢迎的前端框架.Bootstrap 是基于 HTML.CSS. ...

  3. 【前端学习笔记】JavaScript + jQuery + Vue.js + Element-UI

    前端学习笔记 JavaScript jQuery Vue.js Element-UI Java 后端部分的笔记:Java 后端笔记 JavaScript 基础语法(数据类型.字符串.数组.对象.Map ...

  4. 前端学习笔记(this)

    前端学习笔记(this) 在函数中调用 在函数中直接调用 函数作为对象的方法进行调用 不在函数中调用 es6的箭头函数 在函数中调用 在函数中直接调用 1 严格模式和非严格模式中this 严格模式下t ...

  5. 前端学习笔记(js基础知识)

    前端学习笔记(js基础知识) JavaScript 输出 JavaScript 数据类型 常见的HTML事件 DOM 冒泡与捕获 流程控制语句 for..in 计时器 let,var,const的区别 ...

  6. 前端学习笔记:省市区三级联动

    前端学习笔记:省市区三级联动 一.数据库 sql表是自关联的表. 表名:province_city_district 字段: id:区域自身的id pid:区域的父级id name:区域自身的名字 二 ...

  7. 前端学习笔记之CSS3基础语法与盒模型(二)

    前端学习笔记之 CSS3基础语法与盒模型 CSS3简介 CSS(cascading style sheet,层叠式样式表)是用来给HTML标签添加样式的语言 CSS3是CSS的最新版本,增加了大量的样 ...

  8. 前端学习笔记36-水平方向的布局

    前端学习笔记36-水平方向的布局 上一节中的margin-right是没用的,为什么呢? 子元素的七个水平布局设置: margin-left border-left padding-left widt ...

  9. web前端学习笔记(最新)

    web前端学习笔记 大家好,我是链表哥,新的学期,新的学习,我会为您展示我的学习进程. 一:什么是WEB前端? 所谓的Web前端指的是用户所能接触到的,并服务于用户的前沿端口,经我们程序员编辑修饰后展 ...

  10. 前端学习笔记(HTMLCSS)(06)CSS盒子模型练习

    前端学习笔记(HTML&CSS)(06) 练习一:图片列表 <!DOCTYPE html> <html lang="en"> <head> ...

最新文章

  1. apache安装_Apache+PHP 安装 ---windows
  2. 从火热到理性,2019年AI芯片行业发展的怎么样了?【附PPT下载】
  3. JVM Class详解之一
  4. wxpython实现鼠标拖动事件
  5. 啊啊啊...每次需求评审总被boss虐成狗?解药来了
  6. idea:打包jar(原文by曲高终和寡)
  7. mongodb系列01--基础篇
  8. OenLayers 事件注册
  9. iOS: OC/Swift使用CocoaPods生成Podfile文件、安装第三方SDK
  10. sql中DistinctCount的用法
  11. html如何做滑动门效果,JS+CSS实现简易的滑动门效果代码
  12. 钉钉机器人智能提醒_使用钉钉机器人定时发送消息
  13. 朋友圈点赞、发红包 测试用例的设计点
  14. python3爬虫数据清洗与可视化实战pdf百度云_Python 3爬虫、数据清洗与可视化实战_PDF电子书...
  15. 【Python 百炼成钢】进制转换、特殊回文数、水仙花数、杨辉三角、字母图形、01字符串、回形取数、排他方数、世纪末的星期日、约瑟夫环
  16. 计算机二级考试c语言冲刺,计算机二级考试试题C语言冲刺试题
  17. .NET北京俱乐部,技术的饕餮盛宴,不枉此行
  18. 基于PaddleDetection-YOLOV3做一个完整的图形目标检测项目
  19. 诺基亚6升级+Android8,诺基亚6.2喜迎Android10操作系统更新
  20. 玉石效果?——UnityShader学习笔记

热门文章

  1. TypeScript基础入门 - 接口 - 继承接口
  2. 第 4 章 Hypertable
  3. JdbcTemplate(1)(数据连接池)
  4. 视频直播营销时代已来,企业该如何把握这波红利?
  5. swift为UIView添加extension扩展frame
  6. eclipse提交项目到github
  7. 生成器generator
  8. 火力发电厂与变电站设计防火规范_建筑内部装修设计防火规范-GB 50222-2017
  9. python中类的嵌套_python类的嵌套
  10. 5G/4G:空口MAC层架构的简要变化。