1.作用域

可访问变量,对象,函数的集合,是一个独立的空间,让变量不会外泄,作用就是隔离变量

作用域种类:

  • 全局作用域(window, document)
  • 函数作用域(当前函数中)
  • 块级作用域(大括号{}}里, const let 声明,if语句和for语句里面的{ }也属于块作用域,每次循环都产生一个块级作用域 )

// es6块级作用域

If (true) {let x = 100
}
console.log(x) // 会报错

var let const 区别

  • var let声明变量,const声明常量
  • let只在当前作用域生效,不能跨块访问,也不能跨函数访问
for(let I = 0; I< 10; I++) {let a = 4
}
console.log(I) // I is not defined
console.log(a) // a is not defined
  • var可全局访问,能跨块访问,不能跨函数访问
for (var j = 0; j < 10; I++){var a = 5
}
console.log(j) // 10
console.log(a) // 5
  • var存在变量提升,可以先使用后声明,只不过变量是Undefined,
    而let先使用后声明会报错 is not undefined
console.log(a) // undefined
var a = 4console.log(b) // b is not defined
let b = 12

undefined 和 is not defined

undefined是js基本数据类型变量未赋值或者函数没有返回值时返回
is not defined变量未定义,是一种错误类型

自由变量

没被定义但被使用的变量,一层一层向上级作用域查找,如果找到全局都没找到,报错 xx is not defined

作用域链

在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,形成一个链条
在创建时候就确定了的

2. This(取值是在函数执行时确认的!!!不是函数定义时确认的!)

This的不同应用场景,如何取值?
  • 作为普通函数去调用(window)
  • 使用call apply bind去调用(传入的值)
  • 作为对象方法被调用(返回对象)
  • 在构造函数或者类中调用(返回实例)
  • 箭头函数(返回上一级this值)

// 作为普通函数调用

Function fn1() {console.log(this)
}
fn1() // window,

// 使用call调用

fn1.call({ x: 100 }) // {x: 100}

// 使用bind调用

const fn2 = fn1.bind({ x: 200 }) // bind返回一个新函数
fn2() // 200, 所以要执行新函数

// 作为对象方法调用

const zhangsan = {name: ‘张三’,sayHi() {// 作为对象方法被执行,返回当前对象,this即当前对象console.log(this)},wait() {setTimeout(function(){// 是setTimeout函数执行的打印this,作为一个普通方法去执行,而不是作为sayHi()对象方法执行的,所以this === window// setTimeout执行函数中的this永远指向window,因为setTimeout是挂载到window上执行的,调用的代码运行在与所在函数完全分离的执行环境上console.log(this)})}
}

// 箭头函数调用

const  zhangsan = {name: ‘张三’,sayHi() {// this即当前对象console.log(this)},waitAgain() {console.log(this) // 同样作为对象方法被执行,this=== 当前对象setTimeout(() => {// 箭头函数的this永远取它上级作用域的this值,它自己本身不会决定this的值,this即当前对象console.log(this)})}
}

// class方法中调用

class People {constructor(name) {this.name = name // 此处this为当前创建的实例zhangsanthis.age = 20}sayHi() {console.log(this) // 此处this也是当前实例zhangsan}
}const zhangsan = new People(‘张三’)
zhangsan.sayHi() // People {name: '张三', age: 20}


class Student extends People     {constructor(name, number) {super(name)this.number = number}sayHi() {console.log(`姓名 ${this.name} 年龄 ${this.age}`)// 打印当前对象}
}
const xialuo = new Student(‘xialuo’, 18)
xialuo.sayHi() // sayHi为xialuo对象上的方法,此对象上有name age属性

xialuo._proto_.sayHi() // undefined因为这里的sayHi被当作 xialuo._proto_隐式原型对象上的方法,这个隐式原型对象上没有name和age属性


xialuo.__proto__.sayHi.call(xialuo)

bind函数的使用(谁执行this就指向谁)

Function fn1(a, b, c) {console.log(‘this’, this)console.log(a, b , c)return ‘this is fn1’
}const fn2 = fn1.bind1({ x: 100}, 10, 20)
const res = fn2()
console.log(res)

手写bind函数 - bind(要绑定的this,参数,参数…)

// class原型函数

Function.prototype.bind1 = function() {// 1.将参数arguments解析为数组, const args = Array.prototype.slice.call(arguments) // 将arguments赋值给Array.prototype.slice的this,通过slice分隔成数组// 2.获取 this(取出数组第一项,数组剩余的就是传递的参数)const that = args.shift() // 指bind函数中第一个要指向的参数{x: 1000}const self = this  // 调用bind的函数或者对象,此处指当前函数 fn1.bind(…)中的fn1// 返回一个函数return function() { //  const fn2 = fn1.bind1({ x: 100}, 10, 20)// 执行原函数,并返回结果 // const res = fn2()return self.apply(that, args) // apply(this, 参数列表)}
}

箭头函数和普通函数的区别

1.this指向不一样,普通 函数作用域为调用它的对象,箭头函数为当前上下文(如声明在全局那么this的作用域即为上下文)
2.arguments,普通函数可通过arguments来实现重载。箭头函数没有arguments,代替的是...rest(剩余参数)
3.原型对象,普通函数有自己的原型对象,箭头函数没有原型对象
4.new实例化,箭头函数不能作为构造函数,使用New 实例化
5.箭头函数简短,通常是匿名函数

3.闭包:

从一个作用域可以使用另一个作用域的变量,比如在函数里返回一个函数,将内部 变量return出去,在外部可以使

  • 函数作为参数被传递
function print(fn) {let a = 200fn()
}
let a = 100
function fn() {console.log(a)
}
print(fn) // 100, 变量查找在函数定义的地方,不是函数调用的地方
  • 函数作为返回值被返回
function create() {let a = 100return function() {console.log(a)}
}let fn = create()
let a = 200
fn() // 100,变量查找在函数定义的地方,不是函数调用的地方

内存泄漏:变量没有再被引用,且没被垃圾回收机制清除。

1)闭包就是函数里嵌套函数,并return出去。它可以访问其他函数的内部变量,或者一直被引用并不经过内存回收机制,所以闭包会引起内存泄漏。
2)避免闭包引起的内存泄漏,我们可以在退出函数之前,将不使用的局部变量赋值为null。

闭包常用场景

1.小范围内使用全局变量,返回一个或者几个函数,调用执行

exp1:

(fuction() {var test2 = 2function outer() {alert(test2)}function test() {alert('测试闭包', test2)}outer()test()
})() alert(test2) // 在函数外访问不到test2

addEventListener写在函数内部

window.onload = function() {btn.addEventListener('click', function(){...})
}

3.接收一个回调函数作为参数然后执行

封装一个请求接口的方法,调用后执行传递进来的回调函数

function requestUrl(callback) {let promise = new promise((resolve, reject) => {this.$http.get('http: //...').then((res) => {resolve(res)callback()}).catch(err => {reject(err)})})
}

4.提供一个隐藏数据的api(跟vue的数据劫持有点像)

function createCache() {const data = {}return {set: function(key, value) {data[key] = value},get: function(key) {return data[key]}}
}
const c = createCache()
c.set('a', 100)
c.get('a')

因为不可以直接读取修改data,只可以通过get与set方法去读写,所以相当于隐藏了数据

this作用域和闭包相关推荐

  1. 异步、作用域、闭包--setTimeout在for循环中的思考

    题目: for(var i=0;i<=3;i++){ setTimeout(function() {  console.log(i)  }, 10);} 理想答案是输出:0,1,2,3 实际答案 ...

  2. 你不懂的JS学习笔记(作用域和闭包)

    You don't KnowJS 引语:你不懂的JS这本书github上已经有了7w的star最近也是张野大大给我推荐了一波,阅读过之后感觉对js的基础又有了更好的理解.本来我是从来不这种读书笔记的, ...

  3. 什么是闭包?变量作用域和闭包。

    变量作用域和闭包 变量作用域 当我们写 js 文档的时候经常会设置变量,变量的类型有两种: 全局变量 局部变量 这两种类型的变量有者不同的作用范围,全局变量的作用范围是面向整个文档的,可以称之为全局作 ...

  4. javascript函数作用域与闭包

    8.8. 函数作用域与闭包        如第四章所述,JavaScript函数的函数体在局部作用域中执行,局部作用域不同于全局作用域.本章将解释这些内容和相关的作用域问题,包括闭包.[*] [*] ...

  5. JS一起学03:js组成、下拉+text、字符串拼接、分号问题、数据类型、变量类型、作用域和闭包、命名、运算符、流程判断、调试、iNow、onchang

    一.javaScript组成     1.ECMAScript:解释器.翻译 ---------------------------------------------------------几乎没有 ...

  6. javascript中关于作用域和闭包

    列表项目 前言 学习了javascript已经很久了,关于这个语言中的这两个特性也是早已耳熟能详,但是在实际的使用的过程中或者是遇到相关的问题的时候,还是不能很好的解决. 因此我觉得很有必要深入的学习 ...

  7. 函数作用域,闭包,数据类型的题目

    第一题:函数作用域和闭包 var a = 9 function fn(){a = 0return function (b){return b+a++} } var f = fn() console.l ...

  8. 名称空间与作用域、闭包函数、 装饰器

    1 名称空间与作用域 2  闭包函数 3  装饰器 6.7 名称空间与作用域 内置名称空间: 存放的是:内置的名字与值的绑定关系 生效:python解释器启动 失效:Python解释器关闭 全局名称空 ...

  9. js 预编译 解释执行 作用域链 闭包

    <script>var a,b = 1;function c(x){var aa = 2;function d(){var ab = 3;}}var d = function(){//.. ...

  10. (六)JS基础知识三(走进作用域和闭包)【三座大山之二,不会闭包,基本不会通过】

    JS基础知识三(作用域和闭包) 提问 作用域 自由变量 闭包 this 提问 this的不同应用场景,如何取值 手写bind函数 实际开发中闭包的应用场景,举例说明 创建10个a标签,点击的时候弹出对 ...

最新文章

  1. [原]SSL 开发简述(Delphi)
  2. php混合运算计算器,混合运算计算器
  3. 用DDA Convolution和Perlin Noise来模拟水粉画笔触
  4. linux脚本怎么把文件地址变成动态地址,Linux脚本程序自动修改网卡配置文件中的MAC地址...
  5. 计算机专项能力局域网管理,全国计算机信息技术考试局域网管理(Windows NT平台)管理员级考试考试大纲...
  6. 网关屏蔽mac地址,linux下修改mac地址方法
  7. SpringBoot 2.3.x gradle源码构建
  8. 【Web理论篇】Web应用程序安全与风险
  9. HDU - 5699(79/600)
  10. 物联网的体系结构分为_物联网体系结构分为哪三层
  11. DataGrip 保姆级教程 !
  12. IDEA背景色和背景图片的设置
  13. 二硫化锡/纳米碳/MXene/PANI复合材料研究进展
  14. element ui 中 el-checkbox-group 点击一个全部选中的问题
  15. 华为LACP链路聚合配置
  16. 中台搞了2年,项目叫停,CIO被裁!本以为中台是道送分题,没想到是送命题!...
  17. 软件设计师---计算机系统
  18. 溢出漏洞,缓冲区溢出漏洞
  19. memcpy 函数详解
  20. 如何选择socks5免费代理地址呢?

热门文章

  1. 【智能合约审计】————23、EthLendToken
  2. 数据结构(选择练习)
  3. Java反射原理理解
  4. linux和windows的异同
  5. excel怎么更改坐标轴刻度_excel表格改坐标轴数据-如何改变Excel表格坐标轴刻度的次序...
  6. 2016-2017前端面试题
  7. 千峰JavaDay32课后作业
  8. 【Python】批量下载Google图片
  9. 使用WebGL绘制一只平面小鸡
  10. calibre check