大纲


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. Spring基于注解@Required配置

    基于注解的配置 从 Spring 2.5 开始就可以使用注解来配置依赖注入.而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身. ...

  2. 数据挖掘入门系列教程(十一点五)之CNN网络介绍

    在前面的两篇博客中,我们介绍了DNN(深度神经网络)并使用keras实现了一个简单的DNN.在这篇博客中将介绍CNN(卷积神经网络),然后在下一篇博客中将使用keras构建一个简单的CNN,对cifa ...

  3. SSH公钥登录和RSA非对称加密

    SSH登录方式 接触过Linux服务器的同学肯定用过SSH协议登录系统,通常SSH协议都有两种登录方式:密码口令登录和公钥登陆. 一.密码口令(类似于账号密码登录) 1.客户端连接服务器,服务器把公钥 ...

  4. axios的使用小技巧:如何绕过字符串拼接,直接传递对象

     Vue.js官方推荐使用axios作为发送http请求的工具,在使用axios中,有些小技巧是不容易发现的.当我们不知道这些技巧时,我们可能会使用其他"奇技淫巧",比如,我们很容 ...

  5. Vs Code在Vue项目中v-for指令提示错误的解决办法

    最近在做一个Vue项目,在其中用到v-for指令时,发现Vs Code报错,如下图(代码是没有任何问题的),在网上找了一下解决办法,希望能帮助到更多人. 解决方法: 打开    文件-首选项-设置 将 ...

  6. 更改 vsftpd 的端口号

    2019独角兽企业重金招聘Python工程师标准>>> vsftpd启动后,默认的ftp端口是21,现在我想把ftp端口改成 801 ,修改后能保证用户上传下载不受影响 1.编辑 / ...

  7. WebStorm 2019 3.3 安装及破解教程附汉化教程

    WebStorm2019 3.3 安装及破解教程附加汉化教程 安装包及破解补丁 链接: https://pan.baidu.com/s/19ATTAW3Tsm0huIJSqYChTw 提取码:1ei7 ...

  8. Codeforces Round #590

    题目链接:Round #590 题目答案:官方Editorial.My Solution A. Equalize Prices Again 签到题还WA了一发,向上取整有点问题: //my wrong ...

  9. Nginx模块开发(1)————类helloworld

    Nginx看了一点了,准备写个helloworld试试,觉得只看书的话很多东西都乱乱的,晕晕的,印象不深. 我的helloworld模块的目的就是:能够在浏览器里输入http://你的ip地址/lcw ...

  10. 虚拟机上图片服务器搭建(FastDFS+nginx)

    文件服务器 0.提前建好需要的文件夹(/home/fastdfs) /home/fastdfs/tracker /home/fastdfs/storage /home/fastdfs/storage/ ...