首先一起回顾下预解析作用域吧:

  预解析:
    浏览器每读到一个script标签或function,先不执行任何代码,会先把整个代码快速的浏览一遍,然后从中 挑出 var 和 function两个关键字 .
    var: 预解析遇到 var 就把 var 连同它后边的名字一块 提到script(或function) 的最前边,预解析完成之后,在从上向下一行一行执行代码,如果碰到了 = 就赋值;
    function:预解析遇到function,就把整个函数提到提到script(或function) 的最前边(跟在var的后边预解析先解析var 在解析 function)

    全局作用域 --- 在任何地方都能访问
                             函数外定义的变量拥有全局作用域
                            不使用var定义的变量拥有全局作用域
                            所有window对象上的属性拥有全局作用域
                            没有声明在任何函数内部的函数拥有全局作用域
      局部作用域 --- 只能在函数内部访问
                            使用var在函数内部定义的变量,和使用function在函数内部声明的函数,拥有局部作用域

[[Scopes]] : 作用域
                            当我们声明一个函数的时候,同时该函数就会创建一个属性这个属性是[[Scopes]](作用域),我们在这个函数中 声明的变量都会被存入这个函数的[[Scopes]]属性中
     变量与函数的查找规则:
                            当我们调用一条数据的时候,js首先会在当前作用域中进行查找,如果找不到,就向上找到父级的作用域,如果在父级的作用域中也找不到,就继续向上查找,直                               到window的作用域。如果在window中也找不到,就报错了

小例子中有涉及到箭头函数,所以我们先认识一下ES6中的箭头函数吧。

// 箭头函数
var fn3 = (a, b) => {
console.log(a, b);
} // 几种有条件的简化写法
// 当参数只有一个的时候
var fn4 = a => {
console.log(a);
}
// 当参数有多个的时候
var fn5 = (a, b) => {
console.log(a, b);
}
// 当没有参数的时候
var fn6 = () => {
console.log();
}
// 有且仅有一个形参的时候,可以省略参数的小括号 // var fn7 = r => {
// return r * r * Math.PI;
// }
// 只有一条语句的时候,可以省略{},同时该条语句的结果将作为该函数的返回值
var fn7 = r => r * r * Math.PI;

下面是箭头函数的特性,主要是this需要多加注意

    在es6中,提供了一种新的函数格式:箭头函数
注意:
1. 箭头函数不能作为构造函数,也就是箭头函数不能使用new运算符
2. 箭头函数的this永远指向当前申明作用域对象 带大括号的范围
1. 普通函数this指向取决于调用
2. 箭头函数this指向取决于申明
3. 箭头函数没有arguments对象
也会因为call的改变指向而改变this。即使在构造函数中。所谓的声明时候的this,也可能是被变化掉了。
 

接着,我们一起来看一个小例子吧!

var name='window';
var person1 = {
name:'person1',
show1: function() {
console.log(this.name)
},
show2: () => console.log(this.name),
show3: function() {
return function() {
console.log(this.name)//这里的this跟外层函数的this没关系
}
},
show4: function(){
return () => console.log(this.name)
}
};
//call是更改this指向的。 //对象属性中的函数,写法相当于 person1.show=function(){}
//函数是全局作用域,挂载到window下,方便理解后面的this指向window var person2 = {name:'person2'};
person1.show1()//person1
//person1是个对象所以这里指向的是对象的this person1 person1.show1.call(person2)//person2
//函数执行前先改了this指向 person1.show2()//window
//函数声明是挂载到window下的,箭头函数与声明作用域对象有关
//即使这里调用该函数执行的是对象,但this还是指的window person1.show2.call(person2)//window
//同上,虽然执行函数时更改了this指向,但是这一套对箭头不好使。所以仍然是window person1.show3()()//window
//person1.show3()得到的其实是function(){console.log(this.name)}
//函数执行,this指向的就是window person1.show3().call(person2)//person2
//person1.show3()得到的其实是function(){console.log(this.name)}
//然而接着在执行function前更改了指向 person1.show3.call(person2)()//window
//person1.show3.call(person2)更改了function() {
// return function() {
// console.log(this.name)
// }
// }
//但再次调用括号执行本质还是跟上面一样,执行的是return出来的内部函数
//先更改的指向是障眼法而已 person1.show4()()//person1
//person1.show4()先执行得到的是() => console.log(this.name)
//再指向该箭头函数,它的声明作用域this指向的是person1 person1.show4().call(person2)//person1
//箭头函数this在声明时候指向的是person1。
//person1.show4()先执行得到的是() => console.log(this.name)
//这里的call是更改箭头函数本身的指向,是改不了的。 person1.show4.call(person2)()//person2
//person1.show4.call(person2)第一步执行这个的时候就先更改了指向
//在执行() => console.log(this.name)前先更改了person1的指向

 

对比: 上面第一个是一个对象而已,所以show2的箭头函数声明时直接指向的window, 下面的是构造函数,能够为s1的箭头函数提供执行环境,所以这里指向的是TImer对象本身。

       以上两种情况是需要注意区别的。

有错误或者不足之处请大家多多指正,谢谢啦!!!

函数作用域中的this问题的更多相关文章

  1. Javascript中的词法作用域、动态作用域、函数作用域和块作用域(四)

    一.js中的词法作用域和动态作用域      词法作用域也就是在词法阶段定义的作用域,也就是说词法作用域在代码书写时就已经确定了.       js中其实只有词法作用域,并没有动态作用域,this的执 ...

  2. JS 函数作用域及变量提升那些事!

    虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...

  3. JS _函数作用域及变量提升

    虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷)&g ...

  4. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  5. 关于JavaScript全局作用域和函数作用域的拙见

    在类c的语言中,用{}引起来的部分称为块级作用域,而在JS中没有块级作用域 作用域:一个变量作用的范围:中Js中一共有两种作用: 全局作用域 - 直接编写在script标签中的JS代码,都在全局作用域 ...

  6. JavaScript 函数作用域的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的.例如 : message = "hello JavaScript ! " ...

  7. JS基础_函数作用域

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. js高级程序设计书中,有一句话在全局作用域中定义的函数实际上只 能被某个对象调用???

    js没有块级作用域(题外话:函数可以作为一个块级),所以我们经常使用闭包来模拟块级作用域,以避免变量或者函数因为名称相同而产生的冲突. 重点来了: 所以,如果我们把哪个变量或者函数放在全局作用域中,那 ...

  9. javascript中不存在块级作用域,所以要小心使用在块级作用域中的函数声明所带来的作用域混乱.

    在javascript中函数的作用域是一个非常重要的概念. javascript中是没有块级作用域,但是有函数作用域的概念. 我们在开发的过程中,经常会遇到这样的问题, 某个函数我暂时不需要,不想声明 ...

随机推荐

  1. ABP从入门到精通(1):aspnet-zero-core项目启动及各项目源码说明

    一.ABP的简单介绍 ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践 ...

  2. 回味Python2.7——笔记1

    一.基本知识 1.一个值可以同时赋给几个变量: >>> x = y = z = 0 # Zero x, y and z >>> x 0 >>> y ...

  3. HTML中关于图像和表格,链接等的知识

    下面是我分享的html中关于图像和表格,链接等知识: ①<img/>图像标签 <img/>标签中的一些常见属性:1,src是图像的路径属性,是img标签中必不可少的属性. 2, ...

  4. useradd新建用户和权限分配

    场景:在搭建Ftp服务器时候,需要新建ftp用户,其实新建的ftp用户和Linux中root新建的用户一样,只是需要了解新建用户时候的相关规则. 1 解决新建用户缺少配置文件 1.1 新建用户 指定目 ...

  5. python开发部署时新增数据库中表的方法

    在项目版本让运维部署时,涉及到数据库表的增加问题,想了一下,可以有四种方法 1.使用SQLAlchemy的db.create_all()方法 # -*- coding:utf-8 -*- from f ...

  6. 【Django】django 的request和response(转)

    当请求一个页面时,Django 把请求的 metadata 数据包装成一个 HttpRequest 对象,然后 Django 加载合适的 view 方法,把这个 HttpRequest 对象作为第一个 ...

  7. ubuntu上安装apache2+mysql+php5-fpm(PHP5 - FastCGI Process Manager)

    1: 安装mysql apt-get install mysql-server mysql-client 安装过程中会被问到设置mysql root的密码     New password for t ...

  8. [HAOI 2005][BZOJ 1054] 移动玩具

    先贴一波题面 1054: [HAOI2008]移动玩具 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2288  Solved: 1270 Descr ...

  9. 33. leetcode 268. Missing Number

    Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missin ...

  10. Trailing Zeroes (III)

    You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in d ...