、为什么要用this

     通过this可以在不同的上下文对象中重复使用函数

二、this是什么

     this就是我们说的执行上下文(包含调用栈(哪里被调用)、函数的调用方式、传入的参数等信息)

三、this的绑定规则

      1、默认绑定

         当函数调用没有引用对象时,默认this指向全局对象

      2、隐式绑定

        this指向函数的调用者

      3、显示绑定

        通过apply/call、bind绑定

      4、new绑定

         this指向new出来的对象

     5、es6的箭头函数,this指向第一个不是箭头函数的函数的父作用域

四、测验

  1、回顾一下闭包的一个例子,搞懂词法作用域的使用

  example1: 

var fun;
var a = 1;
function fn() {
var a = 2;
function foo() {
console.log(a);
} fun = foo;
} function fun2 () {
var a = 3;
fun()
} fn()
fun2()

foo的引用返回给了一个变量fun,fun是全局变量,一直存在内存中,fn执行完,内存不会被销毁,因为内部的变量foo还被引用着,再调用fun2,对foo中的a进行RHS查询,查找到当前词法作用中的a = 2,所以输出为2.

example1输出结果2

example2:

var fun;
var a = 1;
function fn() {
function foo() {
console.log(a);
} fun = foo;
} function fun2 () {
var a = 3;
fun()
} fn()
fun2()  

输出结果1  

闭包只不过是可以让函数的词法作用域一直被引用着,让函数在执行完之后其作用域中的变量仍然能够再被使用。

回顾一下这句话:

     动态作用域的作用域链基于调用栈,而不是代码的作用域嵌套;

     this机制让作用域有了动态作用域的特点;

     js中实质上没有动态作用域,只有词法作用域(什么是词法作用域?词法作用域是一套js引擎如何查找变量以及会在何处查找到变量的规则) 

function t() {
console.log(b)
} function h() {
var b = 4;
t()
} var b = 3;
h()  

输出结果3

什么叫基于调用栈? 基于调用栈就应该是在查找变量时,如果没有查找到变量会基于调用栈向上一层一层的查找,直到查找到或查找至全局作用域。

下面的例子也很清晰的表明了查找变量时,是基于词法作用域的,并不是基于调用栈。(对于详细的词法作用域解释可以看我写的作用域篇)

var a = 0
function bar1() {
var a = 1;
console.log('bar1 ',a)
bar2()//调用位置
} function bar2() {
console.log('bar2 ', a)//调用栈 bar1=>bar2
bar3()//调用位置
} function bar3() {
//调用栈 bar1=>bar2=>bar3
console.log('bar3 ', a)//调用位置
} bar1()

输出:

bar1 1
bar2 0
bar3 0

2、this的默认绑定规则

默认绑定,无论在哪里调用函数,没有引用对象时this指向全局对象:

function foo() {
console.log(this.a)
} var a=2;
(function() {
var a = 3;
foo()
})()  

 输出2  

3、this的隐式绑定规则,可能会出现的绑定对象丢失的情况

 this指向函数的直接调用者,且只有在上一层调用才起作用

function foo() {
console.log(this.a)
} function foo2(fn) {
fn()
} var obj = {
a: 2,
foo: foo
} var a = "global"
obj.foo() //2
foo2(obj.foo)//global

obj.foo当参数传给foo2,参数fn引用着函数foo,调用fn,this又遵循默认绑定,this指向全局对象。  

4、显示绑定

    显示绑定就是通过apply/call、bind来改变函数的this指向;

    当给apply/call第一个参数传递null或undefined的时,默认this指向全局对象;

    

    典型应用场景,创建一个包裹函数,接受参数并返回值。

function add (param) {
return this.a + param
} var obj = {
a: 3
} var bar = function() {
add.apply(obj)
} bar(2)
//5

 bind方法实现:

function add (param) {
return this.a + param
} var obj = {
a: 3
} function bind(fn, obj) {
return function() {
return fn.apply(obj, arguments)
}
} var f = bind(add, obj)
f(2)
//5

  

5、new绑定

 

五、关于this绑定规则的优先级

    显示绑定>隐式绑定

    new绑定>隐式绑定

    硬绑定>隐式绑定

    硬绑定>new绑定

    

    参考学习资料:

    《你不知道的javascript》上

  

Javascript中的this(七)的更多相关文章

  1. javascript中的真假值、数据类型判断以及+的特殊用法

    一.javascript中的假值 jQuery中拥有一组数量奇大的假值,包括 0,NaN(非数),''(空字符串),false,null,undefined 这些值在if判断中全部等于假,但这些值彼此 ...

  2. JavaScript中七种数据类型·中·一

    Standing on Shoulders of Giants; 说到JavaScript里的类型很容易就让人想起 42和"42",分别是string型和number型,但是他们可 ...

  3. JavaScript 中的数据类型

    Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...

  4. Javascript中的valueOf与toString

    基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...

  5. 让你分分钟学会Javascript中的闭包

    Javascript中的闭包 前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它 ...

  6. JavaScript中的正则表达式(终结篇)

    JavaScript中的正则表达式(终结篇) 在之前的几篇文章中,我们了解了正则表达式的基本语法,但那些语法不是针对于某一个特定语言的.这篇博文我们将通过下面几个部分来了解正则表达式在JavaScri ...

  7. 谈谈javascript中的日期Date对象

    一.日期对象  在javascript中并没有日期型的数据类型,但是提供了一个日期对象可以操作日期和时间.  日期对象的创建:  new Date();二.将日期对象转换为字符串  将日期对象转换为字 ...

  8. 深入理解JavaScript中的==运算符

    原文章地址 在详细介绍图1中的每个部分前,我们来复习一下JS中关于类型的知识: JS中的值有两种类型:基本类型.对象类型. 基本类型包括:Undefined.Null.Boolean.Number和S ...

  9. javascript中关于数组的一些鄙视题

    一.判断一个数组中是否有相同的元素 /* * 判断数组中是否有相同的元素的代码 */ // 方案一 function isRepeat1(arrs) { if(arrs.length > 0) ...

  10. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

随机推荐

  1. Unity查找物体的子物体、孙物体

    Unity查找物体下的所有物体 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分 ...

  2. leetcode227. Basic CalculatorII

    这道题是只有四则运算但是没有括号的,因此可以利用stack来存储的,并且每次使得存储的值与符号有对应的关系,最后在栈中只剩下可以利用加法进行处理的数的,注意在i=n-1的时候到达最后的部分也是需要把数 ...

  3. Cocos闪屏视频VideoPlayer踩坑记录

    游戏闪屏动画(Logo&健康游戏公告)使用了 experimental::ui::VideoPlayer 来播放视频 3.7版本开发到目前为止发现2个坑 1.设置大小 _videoPlayer ...

  4. django 浅谈CSRF(Cross-site request forgery)跨站请求伪造

    浅谈CSRF(Cross-site request forgery)跨站请求伪造(写的非常好) 本文目录 一 CSRF是什么 二 CSRF攻击原理 三 CSRF攻击防范 回到目录 一 CSRF是什么 ...

  5. c# 敏捷2 ForEach ToDictionary ToLookup Except比较

    using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; ...

  6. C++学习(二十七)(C语言部分)之 预处理命令

    结构体 联合 枚举 联合 只能保存最后赋值的结果枚举 所有可能值列出来 预处理命令是在编译前期的阶段 代码-(编译)-->可执行文件(exe)预编译 编译前对代码处理 *1.插入头文件的内容 # ...

  7. 实验吧—Web——WP之 what a fuck!这是什么鬼东西?

    打开链接——> 发现是一大堆符号,可能有些人见过这些样子的,这是一种编码方式,叫:jother编码 jother编码是一种运用于javasscript语言中利用少量字符构造精简的匿名函数方法,对 ...

  8. 鸟哥的linux私房菜第4版--自学笔记

    -----------------------------------第一章 intel芯片架构 PS:升级电脑还得看看主板是不是适合CPU,主板适合CPU的类型是有限的PS: 现在已经没有北桥了,已 ...

  9. IntelliJ快捷键笔记

    1.查找文件:Ctrl+Shift+N 2.大小写转换:Ctrl+Shift+U 3.get/set方法快捷键:Alt+Insert 4. 查看类继承关系:Ctrl+H或者Ctrl+Shift+Alt ...

  10. SUPERSOCKET 客户端

    SUPERSOCKET.CLIENTENGINE 简单使用 2015年5月27日 HYJIACAN 发表回复 阅读 11,105 次 江大没有给ClientEngine的Demo,一直没有找到其它的. ...