大纲


scope-作用域

作用域是指程序源代码中定义变量的区域,规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。

JavaScript作用域共有两种主要的工作模型——词法作用域(静态作用域)和动态作用域。

JavaScript默认采用词法作用域(lexical scoping),也就是静态作用域。

词法作用域是由开发者在写代码时将变量和块作用域写在哪里来决定的。由此出现全局作用域,函数作用域(局部作用域),块状作用域

动态作用域一般由this产生

注:1.如果一个变量或者表达式不在“当前的作用域”,那么JavaScript机制会继续沿着作用域链向上查找直到全局作用域(global或浏览器中的window)如果找不到将不判定为不可被使用。

    2.作用域也会根据代码层次分层,作用域之间形成父子关系,嵌套关系。子作用域可以访问父作用域。通常沿着链式的作用域链查找向上查找,而不能从父作用域引用访问子作用域的变量和引用

全局作用域

所有在全局作用域中声明的变量、函数都会变成window对象的属性和方法

变量在函数或者代码块{}外定义,即为全局作用域。一般可以在页面任何地方访问

var oneName = " Volvo";
// 此处可调用 oneName 变量
function myFunction() {
// 函数内可调用 oneName 变量
}
if(true){
//代码块内可调用oneName变量
}

在函数或者代码块{}内未定义的变量也拥有全局作用域。该变量将作为global或者window的属性存在

// 此处可调用 oneName 变量
function myFunction() {
carName = "Volvo";
// 函数内可调用 oneName 变量
}
if(true){
//代码块内可调用oneName变量
}

注:在函数内部或者代码块中没有定义的变量实际上是作为global/window的属性存在,而不是全局变量。该变量是可以被delete掉,而全局变量不可以。因为通过var语句添加的全局变量有一个configcurable属性,默认值为false。可以通过Object.getOwnPropertyDescriptor(window,"...")查看

window对象上的属性在书写时可以省略window.

函数作用域(局部作用域)

在函数内部定义的变量对外是封闭的,从外层无法直接访问函数内部的作用域

function bar() {
var testValue = 'inner';
}
console.log(testValue); // 报错:ReferenceError: testValue is not defined

如果想读取函数内部的变量,必须借助return或者闭包

//使用return方式
function bar(value) {
var testValue = 'inner';
return testValue + value;
}
console.log(bar('fun')); // "innerfun"

return 是函数对外交流的出口,而 return 可以返回的是函数,根据作用域的规则,函数bar内部的子函数inner是可以获取函数bar作用域内的变量result

//使用闭包方式
function bar(value) {
var testValue = 'inner';
var result = testValue + value;
function innser() {
return result;
};
return innser();
}
console.log(bar('fun')); // "innerfun"

块状作用域

在其他编程语言中,块状作用域是很熟悉的概念,但是在JavaScript中不被支持。在ES6中已经有了{}块状作用域。

if(true){
let a = 1
console.log(a) //1
}
console.log(a) //a is not defined

注:事实上块状作用域在ES3就已经存在,只是不明显。比如catch块捕获的异常仅在catch块可见

词法作用域(静态作用域)与动态作用域

在javaScript采用词法作用域,执行foo函数,先从foo函数内部查找局部变量value,如果没有,就根据书写的位置,查找上面一层的代码,也就是value等于1,所以结果会打印1

var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();
// 结果是1

这里 bind 已经把作用域的范围进行了修改指向了 { a: 2 },而 this 指向的是当前作用域对象

window.a = 3
function test () {
console.log(this.a)
}
test.bind({ a: 2 })() // 2
test() // 3

如果要开启动态作用域请借助 bind、with、eval 等。

let&Const

let&Const是ES6之后的语法。let拥有的特性Const都拥有。在ES6之后声明变量有6个方式var,function,let,const,import,class

var命令和function命令声明的全局变量依然是顶层对像(window/global)的成员。但let,const,class命令声明的全局变量,不在属于顶层对象的成员。从ES6开始全局变量将逐步与顶层对象的属性脱钩。

注:let和Const声明的变量去哪了?参考https://juejin.im/post/5c0be11b6fb9a049df23e388#heading-1

let

let声明的变量拥有块级作用域

{
let a = 1
}
console.log(a); //undefined

let声明的全局变量不是全局对象的属性

不可以通过window变量名的方式访问这些变量,而var声明的全局变量是window的属性,是可以通过window变量名的访问

var a = 1
console.log(window.a); //1
let a = 1
console.log(window.a); // undefined

用let重定义变量会抛出一个语法错误,var可以重复定义。

var a = 1
var a = 2
console.log(a) //2
let a = 1
let a = 2
// VM131:1 Uncaught SyntaxError: Identifier 'a' has already been declared
// at <anonymous>:1:1

let声明的变量不会进行变量提升,存在暂时性死区(TDZ)。在死区结束前变量不会初始化,在这个区间即使是使用typeof()也会报错

function test () {
console.log(a)
var a = 1
}
test() //undefined
function test () {//TDZ开始
console.log(a)// Cannot access 'a' before initialization
typeof(a)// Cannot access 'a' before initialization
...
...
let a = 1 //TDZ结束
}
test()
// Uncaught ReferenceError: Cannot access 'a' before initialization

const

Const除了具有let的块级作用域和不会变量,并且它定义的常量,在用const定义变量后,就不能修改。对其修改会抛出异常

const PI = 3.1415;
console.log(PI);
PI = 22;
console.log(PI);
// Uncaught TypeError: Assignment to constant variable.

const声明的变量必须进行初始化,否则会抛出异常Uncaught SyntaxError: Missing initializer in const declaration

const PI
PI = 3.1415
// Uncaught SyntaxError: Missing initializer in const declaration

Array

ES6新增了一些实用的原生API,方便开发者对Array的操控性更强。

ES5操作数组的方法 concat、join、push、pop、shift、unshift、slice、splice、substring 和 substr 、sort、 reverse、indexOf 和 lastIndexOf 、every、some、filter、map、forEach、reduce

ES6新增操作数组的方法 find、findIndex、fill、copyWithin、Array.from、Array.of、entries、values、key、includes

围绕数组产生的动作无非是遍历,转换,生成,查找。。。。。。(数据库增删改查一样一样的)

数组遍历的方法有很多例如for循环,forEach,every,for...in,for...of等等

数组的遍历

举几个例子

for循环

for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}

forEach

forEach ( ) 方法。等同于for,不支持break;continue,会抛出异常

forEach()对于空数组是不会执行回调函数的

array.forEach(function(i){
console.log(i);
})
[1,2,3,4,5].forEach(function(i){
if(i===2){
return;
}else{
console.log(i) //1,3,4,5
}
})

every

every()方法遍历可以达到break效果。

every的代码块种仍然不能使用break,continue,会抛出异常

[1,2,3,4,5].every(function(i){
if(i===2){
return false; //return false等同于break
}else{
console.log(i)
return true // return true 等同于continue
}
})

for...in

for... in 的目的是用来遍历对象,而数组刚好是可遍历对象。。。

for (var index in array) {
//index是索引值,是字符串
console.log(array[index]);
}

for...of

for…of是支持 break、continue的,所以在功能上非常贴近原生的 for。

for…of 遍历的是一切可遍历的元素(数组、对象、集合)等。ES6 中允许开发者自定义遍历

for (variable of iterable) {}

variable:每个迭代的属性值被分配给该变量

iterable:一个具有可枚举属性并且可以迭代的对象

数组转换功能

伪数组 具有length属性; 按索引方式存储数据; 不能调用数组的方法

ES5伪数组转换为数组

let args = [].slice.call(arguments)

let imgs= [].slice.call(document.querySelectorAll('img'))//NodeList

ES6伪数组转换为数组

let args = Array.from(arguments)

let imgs = Array.from(document.querySelectorAll('img'))

Array.from(arrayLike,mapFn,thisArg)
//arrayLike 必选 想要转换成数组的伪数组对象或可迭代对象
//mapFn 可选 新数组中的每个元素会执行该回调函数
//thisArg 可选 执行回调函数 mapFn 时 this 对象

数组的生成

ES5初始化一个长度为5的数组,每个数组元素有默认值

Array.from({ length: 5 }, function () { return 1 })

ES6初始化一个长度为5的数组,每个数组元素有默认值

Array.prototype.from()方法

Array.from({ length: 5 }, function () { return 1 })

Array.prototype.of()方法

Array.of(element0[, element1[, ...[, elementN]]])
elementN 任意个参数,将按顺序成为返回数组中的元素。
Array.of(7); // [7]
Array.of(1, 2, 3); // [1, 2, 3] Array(7); // [ , , , , , , ]
Array(1, 2, 3); // [1, 2, 3]

Array.prototype.fill()方法

fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。

let array = [1, 2, 3, 4]
array.fill(0, 1, 2)
// [1,0,3,4] arr.fill(value[, start[, end]])
value 必选 用来填充数组元素的值
start 可选 起始索引,默认值为0
end 可选 终止索引,默认值为this.length

数组的查找

ES6新增查找方法find(),findIndex()

Array.prototype.find()方法

find() 方法返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。

let array = [5, 12, 8, 130, 44];
let found = array.find(function(element) {
return element > 10;
});
console.log(found);// 12
array.find(function(currentValue, index, arr),thisValue)
//function(currentValue, index, arr) 在数组每一项上执行的函数
//currentValue 当前遍历到的元素
//index 当前遍历到的索引
//array 数组本身
//thisArg 执行回调时用作this的对象

Array.prototype.findIndex()方法

findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。其实这个和 find() 是成对的,不同的是它返回的是索引而不是值

ES6-10笔记(一)的更多相关文章

  1. ES6入门笔记

    ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...

  2. es6学习笔记-class之一概念

    前段时间复习了面向对象这一部分,其中提到在es6之前,Javasript是没有类的概念的,只从es6之后出现了类的概念和继承.于是乎,花时间学习一下class. 简介 JavaScript 语言中,生 ...

  3. ES6学习笔记<四> default、rest、Multi-line Strings

    default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...

  4. ES6学习笔记<三> 生成器函数与yield

    为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...

  5. ES6学习笔记<二>arrow functions 箭头函数、template string、destructuring

    接着上一篇的说. arrow functions 箭头函数 => 更便捷的函数声明 document.getElementById("click_1").onclick = ...

  6. ES6读书笔记(三)

    前言 前段时间整理了ES6的读书笔记:<ES6读书笔记(一)>,<ES6读书笔记(二)>,现在为第三篇,本篇内容包括: 一.Promise 二.Iterator和for of循 ...

  7. ES6读书笔记(二)

    前言 前段时间整理了ES6的读书笔记:<ES6读书笔记(一)>,现在为第二篇,本篇内容包括: 一.数组扩展 二.对象扩展 三.函数扩展 四.Set和Map数据结构 五.Reflect 本文 ...

  8. ES6学习笔记之块级作用域

    ES6学习笔记:块级作用域 作用域分类 全局作用域 局部作用域 块级作用域 全局作用域示例 var i=2; for (var i = 0; i < 10; i++) { } console.l ...

  9. ES6学习笔记之变量的解构赋值

    变量的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 数组的解构赋值 以前,为变量赋值,只能直接指定值: 1 2 3 var a = 1; var b = 2; ...

  10. JS&ES6学习笔记(持续更新)

    ES6学习笔记(2019.7.29) 目录 ES6学习笔记(2019.7.29) let和const let let 基本用法 let 不存在变量提升 暂时性死区 不允许重复声明 块级作用域 级作用域 ...

随机推荐

  1. 总结vscode调试vue,nodejs的各种方法

    之前写项目一直都是console.log()来调试的,浪费了很多时间,现在整理一下用vscode对nuxt(vue)前后端进行调试的方法 前端的调试 chrome+launch 使用chrome调试, ...

  2. MacOs下安装Kong网关

    写在前面: 持续记录一下自己在解决api网关kong上的各种问题. 1.关于Kong网关 这是官网地址:https://konghq.com/ 2.通过brew安装postgres 因为kong的数据 ...

  3. JDK14的新特性:Lombok的终结者record

    目录 简介 新的Record类型 探讨Record的秘密 record扩展 总结 JDK 14的新特性:Lombok的终结者record 简介 自从面向对象产生之后,程序界就开始了新的变化,先是C发展 ...

  4. HDU 5725 Game

    1. 笔记 题意是求距离的期望(距离仍指连接两点且有效的路径长度的最小值).直观想象可以发现,该距离与曼哈顿距离相比最多多2(可以构造这样的路径). 答案=(任意两点曼哈顿距离的总和 - 至少有一点是 ...

  5. (转)ATOM介绍和使用

    一,Atom介绍 Atom 是 Github 开源的文本编辑器,这个编辑器完全是使用Web技术构建的(基于Node-Webkit).启动速度快,提供很多常用功能的插件和主题,可以说Atom已经足以胜任 ...

  6. Flex 布局教程:语法篇(转自阮一峰的网络日志)

    作者:阮一峰(转自阮一峰的网络日志,如有侵权,立即删除) 网页布局(layout)是 CSS 的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 ...

  7. H5 -- 取消a标签在点击时的背景颜色

    原文链接:点我 1.取消a标签在移动端点击时的蓝色 a { -webkit-tap-highlight-color: rgba(255, 255, 255, 0); -webkit-user-sele ...

  8. 无向图求割(找桥)tarjan

    本博客参考了李煜东的<算法竞赛进阶指南>,大家要是觉得这篇文章写的不错请大家支持正版.豆瓣图书 我在之前的博客中讲解了搜索序时间戳,这次我们讲讲追溯值的概念. 追溯值: 设subtree( ...

  9. poj1679 The Unique MST(最小生成树唯一性)

    最小生成树的唯一性,部分参考了oi-wiki 如果一条不在最小生成树边集内的边,它可以替换一条在最小生成树边集内,且权值相等的边,那么最小生成树不是唯一的 同过kruskal来判断 考虑权值相等的边, ...

  10. Nacos作为配置中心时,多个服务共用一个dataId的配置

    写在前面 本文是对我之前一篇文章<Spring Cloud+nacos+Feign,实现注册中心及配置中心>的补充.此文章中简单写了如何将Nacos作为配置中心.在使用配置中心时,我们会遇 ...