摘要:使用定义常量应该注意,的作用域与命令相同只在声明所在的块级作用域内有效。,命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。使用的时候,也是直接对类使用命令,跟构造函数的用法完全一致。执行父级的构造函数。
一,let块级作用域
由于js的历史原因。javascript里的es6规范之前,只要函数作用域。当写一些大型的项目代码中,很容易产生全局变量,例如:
点击每个按钮,都结果都是4;
0,1,2,3
当使用let定义变量的时候。点击每个按钮,都结果显示的都是对应的i值。
现在我们可以使用let 定义块级变量。 只在代码块{}内生效;
如:
弹1
报错
使用块级应该注意:
1.块级作用域
for(var i = 0; i < 10; i++){} console.log(i); //10 for(let j = 0; j < 10; j++){} console.log(j); //"ReferenceError: j is not defined
2.不存在变量提升
会报错,ReferenceError
console.log(a); // 输出undefined console.log(b); // 报错ReferenceError console.log(c); // 报错ReferenceError var a = 2; let b = 2;
3.暂时性死区(TDZ)
只要进入当前块级作用域,所使用的变量已经存在了,但在声明之前都属于死区,不可进行操作。
typeof x; // ReferenceError typeof y // undefined let x;
4.不允许重复声明
let x = 1; let x; // "SyntaxError: Identifier "x" has already been declared var y = 2; var y = 3; // y = 3
5.声明的全局变量不再是window的属性
"use strict"; var a = 1; console.log(window.a) // 1 let b = 1; console.log(window.b) // undefined二,const定义常量
const声明一个只读的常量。一旦声明,常量的值就不能改变
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable.
上面代码表明改变常量的值会报错。
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
const foo; // SyntaxError: Missing initializer in const declaration 使用const定义常量应该注意:
1,const的作用域与let命令相同:只在声明所在的块级作用域内有效。
2,const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
3,const声明的常量,也与let一样不可重复声明。
const本质:
const实际上保证的并不是变量值不得改动,而是变量指向的那个内存地址不得改变。对于简单类型的数据(数值,字符串,布尔值),值就是指向的那个内存地址,因此等同于常量。但是对于复合类型的数据(注意是对象和数组),变量指向的是内存地址,保存的只是一个指针,const只能保证这个指针是固定的,至于他指向的数据机构是不是可变的,就不能控制了,因此,将一个对象声明为常量是非常小心的。
const foo = {}; // 为 foo 添加一个属性,可以成功 foo.prop = 123; foo.prop // 123 // 将 foo 指向另一个对象,就会报错 foo = {}; // TypeError: "foo" is read-only
上面代码中,常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。
下面是另一个例子。
const a = []; a.push("Hello"); // 可执行 a.length = 0; // 可执行 a = ["Dave"]; // 报错 上面代码中,常量a是一个数组,这个数组本身是可写的,但是如果将另一个数组赋值给a,就会报错。
ES6 声明变量的六种方法 ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。三,函数参数扩展
rest 参数
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum; } console.log(add(2, 5, 3)) // 10
注意在es6中rest参数只可以是形参的最后一位参数。不然会报错
function add(...values,a) { let sum = 0; for (var val of values) { sum += val; } return sum; } console.log(add(2, 5, 3))四,箭头函数:
之前我们定义一个函数是这样的:
let add=function () { alert(123) } add()
现在我们可以改成箭头函数
let ale=()=>{alert(234)}
ale()
改成箭头函数无非就是把代码简写了,应该注意一下三点:
1,把普通函数的function换成=>.
2,如果只有一个参数,那么()可省略不写。
2,如果只有一个return 那么{}可省略不写。
例如:
1,数组的解构赋值
基本用法
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
以前,为变量赋值,只能直接指定值。
let a=1 let b=2 let c=3
ES6 允许写成下面这样。
let [a, b, c] = [1, 2, 3];
上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子
let [foo, [[bar], baz]] = [1, [[2], 3]]; foo // 1 bar // 2 baz // 3 let [ , , third] = ["foo", "bar", "baz"]; third // "baz" let [x, , y] = [1, 2, 3]; x // 1 y // 3 let [head, ...tail] = [1, 2, 3, 4]; head // 1 tail // [2, 3, 4] let [x, y, ...z] = ["a"]; x // "a" y // undefined z // []
如果解构不成功,变量的值就等于undefined。以下两种情况都属于解构不成功,foo的值都会等于undefined。
let [foo] = []; let [bar, foo] = [1];五,数组
es6中数组有常用的四个方法依次是:
map ----映射 一个对一个
reduce -----汇总 一堆出来一个
filter -----过滤器
forEach -----循环(迭代)
1.map用法
也可改成箭头函数
循环数组,每次都乘2倍,并返回新数组
2.reduce
let arr=[2,14,31,1,4,3] arr.reduce(function(a,b,c){ alert(a+","+b+","+c) })
先看弹什么结果,依次是
先看结果。明显 c参数是下标index,但是有不是0开始。
b是当前的数。 其实a就是最终结果,把上一次算好的数当成了这次的中间结果。 let arr=[2,14,31,1,4,3] let result=arr.reduce(function(tmp,item,index){ return tmp+item }) alert(result)
这就是求和的方式
reduce 流程图
求平均数
let arr=[2,14,31,1,4,3] let result=arr.reduce(function(tmp,item,index){ if(index !=arr.length-1){ //不是最后一项 return tmp+item }else{ //最后一项 return (tmp+item)/arr.length } }) alert(result)
3.filter 过滤器 留下符合条件的一部分;
通过filter里面的function里返回的true和false判断留或者不留。
let arr=[2,14,31,1,4,3] let arr2=arr.filter(()=>{ return true }) alert(arr2) //[2,14,31,1,4,3]
因为返回的true所以都留下了
let arr=[2,14,31,1,4,3] let arr2=arr.filter(()=>{ return false }) alert(arr2) // [ ]
因为返回的false所以都不留下
下面的取可以被3整除的数
let arr=[2,14,33,1,4,3,66] let arr2=arr.filter((item)=>{ if(item%3==0){ return true }else{ return false } }) alert(arr2) //33,3,66
由于item%3==0本身就是布尔值,所以直接可以return这个,即就可以返回符合条件的数。
所以可以写成,
let arr=[2,14,33,1,4,3,66] let arr2=arr.filter((item)=>{ return item%3==0 }) alert(arr2) //33,3,66
还可以简写成箭头函数
let arr=[2,14,33,1,4,3,66] let arr2=arr.filter(item=>item%3==0) alert(arr2) //33,3,66
4.forEach 就是普通的循环,无法就是写法简单一些,
let arr=[2,14,33,1,4,3,66] arr.forEach(item=>{ alert(item) })
它第二个参数是可选的,是index
let arr=[2,14,33] arr.forEach((item,index)=>{ alert(index+":"+item) }) //0:2 //1:14 //2:33六.字符串
(一):
1.includes():返回布尔值,表示是否找到了参数字符串。
2.startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
3.endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
includes()用法
let s = "Hello world!"; s.startsWith("Hello") // true s.endsWith("!") // true s.includes("o") // true
startsWith()用法
let str="git.baidu.com" switch(true) { case str.startsWith("www."): console.log("www网址") break; case str.startsWith("git."): console.log("git网址") break; default: console.log("其他网址") }
endsWith()用法
let str="1.jpg" switch(true) { case str.endsWith("txt"): console.log("txt文件") break; case str.endsWith("jpg"): console.log("jpg文件") break; default: console.log("其他网址") }
(二):模板字符串 (返单引号`)
$("#result").append( "There are " + basket.count + " " + "items in your basket, " + "" + basket.onSale + " are on sale!" );
大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。
let x = 1; let y = 2; `${x} + ${y} = ${x + y}` // "1 + 2 = 3" `${x} + ${y * 2} = ${x + y * 2}` // "1 + 4 = 5" let obj = {x: 1, y: 2}; `${obj.x + obj.y}` // "3"
模板字符串之中还能调用函数。
function fn() { return "Hello World"; } `foo ${fn()} bar` // foo Hello World bar七.class
JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。
function Point(x, y) { this.x = x; this.y = y; console.log(this,12) } Point.prototype.toString = function () { return "(" + this.x + ", " + this.y + ")"; }; var p = new Point(1, 2); console.log(typeof p.toString())
其不好的地方就是,构造函数和类混为一谈了,别的语言(java)中构造函数就是构造函数,类就是类。
而且代码写了两块,方法通过prototype添加。还有就是这个是es6之前的方式生成对象。es6之前的js里中是没有类的概念的,这些方式都是东拼西凑的。
写到这里,可以暂时回顾一下es6之前的创造对象的时候 new 关键字都做了什么。
要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4
个步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;
(3) 执行构造函数中的代码(为这个新对象添加属性) ;
(4) 返回新对象。
new 操作符
在有上面的基础概念的介绍之后,在加上new操作符,我们就能完成传统面向对象的class + new的方式创建对象,在JavaScript中,我们将这类方式成为Pseudoclassical。
基于上面的例子,我们执行如下代码
var obj = new Base();
new操作符具体干了什么呢?其实很简单,就干了三件事情。
var obj = {}; obj.__proto__ = Base.prototype; Base.call(obj);
第一行,我们创建了一个空对象obj
第二行,我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
第三行,我们将Base函数对象的this指针替换成obj,然后再调用Base函数,于是我们就给obj对象赋值了一个id成员变量,这个成员变量的值是”base”,关于call函数的用法。
如果我们给Base.prototype的对象添加一些函数会有什么效果呢?
例如代码如下:
Base.prototype.toString = function() { return this.id; }
那么当我们使用new创建一个新对象的时候,根据__proto__的特性,toString这个方法也可以做新对象的方法被访问到。于是我们看到了构造子中,我们来设置‘类’的成员变量(例如:例子中的id),构造子对象prototype中我们来设置‘类’的公共方法。于是通过函数对象和Javascript特有的__proto__与prototype成员及new操作符,模拟出类和类实例化的效果。
现在的es6中创作对象的方式就及其简单。
class Point { constructor (x,y){ this.x=x; this.y=y } tostring (){ return "(" + this.x + ", " + this.y + ")"; } } let a=new Point(2,3) alert(typeof a.tostring()) //string
上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而且this关键字则代表实例对象,也就是说,es5的构造函数Point,对应es6的point类的构造方法。
point类除了构造方法,还定义了一个tostring方法。注意,定义’类‘的方法时候,前面不需要加上function这个关键字,直接把函数定义进去级可以了。类外,方法之间不需要逗号分隔,加上会报错。
ES6 的类,完全可以看作构造函数的另一种写法。
class Point { // ... } typeof Point // "function" Point === Point.prototype.constructor // true
上面代码表明,类的数据类型就是函数,类本身就指向构造函数。
使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。
class Bar { doStuff() { console.log("stuff"); } } var b = new Bar(); b.doStuff() // "stuff"
构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。
class Point { constructor() { // ... } toString() { // ... } toValue() { // ... } } // 等同于 Point.prototype = { constructor() {}, toString() {}, toValue() {}, };
在类的实例上面调用方法,其实就是调用原型上的方法。
class B {} let b = new B(); b.constructor === B.prototype.constructor // true
上面代码中,b是B类的实例,它的constructor方法就是B类原型的constructor方法。
由于类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign方法可以很方便地一次向类添加多个方法。
class Point { constructor(){ // ... } } Object.assign(Point.prototype, { toString(){}, toValue(){} });
prototype对象的constructor属性,直接指向“类”的本身,这与 ES5 的行为是一致的。
Point.prototype.constructor === Point // true
另外,类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
七,面相对象
//es5中通过构造函数创建对象 function User (name,password){ this.name=name; this.password=password; console.log(this) } User.prototype.showname = function(){ alert(this.name) } User.prototype.showpass = function(){ alert(this.password) } var user=new User("lee","123") user.showname() user.showpass() // 之前的面相对象缺点: // 1,类和构造函数混为一谈了。 // 2.方法添加到类(构造函数)外面。
es6中创建对象
// es6 class User { //User是类 constructor(name,password){ //constructor是构造函数 this.name=name; this.password=password } //方法写在类里面,而且必须不能有function,多个方法之间不能有‘,’ showname(){ alert(this.name) }, showpass(){ alert(this.password) } } var user = new User ("wang","1234") user.showname() user.showpass()
继承:
es5中的继承:
// 继承es5 function User (name,password){ this.name=name; this.password=password } User.prototype.showname=function(){ alert(this.name) } User.prototype.showpass=function(){ alert(this.password) } function Vipuser(name,password,level){ User.call(this,name,password) this.level=level } Vipuser.prototype=new User() //先new一下 Vipuser.prototype.constructor=Vipuser;//在补一下constructor,因为constructor乱了 Vipuser.prototype.showlevel=function(){ alert(this.level) } var vipuser=new Vipuser("LV","2323",8) vipuser.showname() vipuser.showpass() vipuser.showlevel()
es6中的继承
// 继承es6 class User{ constructor(name,password){ this.name=name; this.password=password; } showname(){ alert(this.name) } showpass(){ alert(this.password) } } class Vipuser extends User { constructor(name,password,level){ super(name,password)//super,超类,父类。执行父级的构造函数。继承父级的属性,相当于es5继承中的User.call(this,name,password) this.level=level } showlevel(){ alert(this.level) } } var vipuser=new Vipuser("dawang","123",9) vipuser.showname() vipuser.showpass() vipuser.showlevel()
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94590.html
摘要:常量变量先说说常量和变量的概念吧,常量是说那种进行一次赋值后不会更改的值,比如说游戏账户的,变量是说赋值后有更改的需求的,比如游戏名,游戏密码。常用实例交换变量的值提取数据解构赋值对提取对象中的数据,尤其有用。 本系列文章适合快速掌握 ES6 入门语法,想深入学习 ES6 的小伙伴可以看看阮一峰老师的《ECMAScript 6 入门》 学习 20% 的知识完成 80% 的工作 关于 ...
摘要:的翻译文档由的维护很多人说,阮老师已经有一本关于的书了入门,觉得看看这本书就足够了。前端的异步解决方案之和异步编程模式在前端开发过程中,显得越来越重要。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。 JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMASc...
摘要:本系列文章适合快速掌握入门语法,想深入学习的小伙伴可以看看阮一峰老师的入门本篇文章是对之前文章的一个补充,可以使代码更简洁函数参数默认值在传统语法中如果想设置函数默认值一般我们采用判断的形式在新的语法中我们可以在参数声明的同时赋予默认值参数 本系列文章适合快速掌握 ES6 入门语法,想深入学习 ES6 的小伙伴可以看看阮一峰老师的《ECMAScript 6 入门》 本篇文章是对之前文章...
摘要:结合工作中使用情况,简单对进行一些复习总结,包括常用的语法,等,以及短时间内要上手需要重点学习的知识点不同工作环境可能有一些差别,主要参考链接是阮一峰的博客以及外文博客阮老师大部分文章是直接翻译的这个博客简介先说一下,是一个标准化组织,他们 结合工作中使用情况,简单对es6进行一些复习总结,包括常用的语法,api等,以及短时间内要上手需要重点学习的知识点(不同工作环境可能有一些差别),...
摘要:在重写完了的时候,就个人总结了一下常用的一些常用的语法和比优越的方面。参数字符串是否在原字符串的尾部返回布尔值。第一个大于的成员的索引方法,用于某个数组是否包含给定的值,返回一个布尔值。 1.前言 前几天,用es6的语法重写了我的一个代码库,说是重写,其实改动的并不多,工作量不大。在重写完了的时候,就个人总结了一下es6常用的一些常用的语法和比es5优越的方面。下面提到的语法可能也就是...
阅读 1768·2021-11-23 09:51
阅读 1219·2021-11-18 10:02
阅读 951·2021-10-25 09:44
阅读 2081·2019-08-26 18:36
阅读 1602·2019-08-26 12:17
阅读 1131·2019-08-26 11:59
阅读 2729·2019-08-23 15:56
阅读 3319·2019-08-23 15:05