JS 进阶(9) ECMAScript6 基础入门:变量、函数、解构赋值、数组、字符串、面向对象、json、promise

12 篇文章 1 订阅

一、ES6是啥

  • ECMAScript 和 JavaScrip的关系
    简单的说ECMA 是一个标准,任何语言都可以去实现这个标准,但目前为止只有javascript 实现了。所以也就默认认为ECMAScript就是javascript。
    ECMAScript 简称 ECMA 或 ES。

  • ECMAScript 历史版本
    1996, ES1.0 Netscape 将 JS 提交给 ECMA 组织,ES 正式出现
    1999, ES3.0 被广泛支持
    2011, ES5.1 成为 ISO 国际标准
    2015, ES6.0 正式发布


二、ES6的兼容性

  • ES6(ES2015) 支持的环境 IE10+, Chrome, FireFox, 移动端, NodeJS

  • 解决不兼容办法,编译、转换

  1. 在线转换
	<script src="browser.js" charset="utf-8"></script>
	<script type="text/babel">
		let a = 3;
		let b = 6;
	</script>
  1. 提前编译
    使用babel编译工具可以将写好的ES6代码编译成ES5(兼容IE8等),甚至也可以编译成ES3(兼容各种低版本的浏览器)

三、变量 let 和 常量 const

  • var 的问题
    • 可以重复声明,没有报错和警告
    • 无法限制修改
    • 没有块级作用域, { }

  • let 和 const

    • 不能重复声明
    • 都是块级作用域, { } 块内声明的,块外无效
    • let 是变量,可以修改
    • const 是常量,不能修改

  • 块级作用域举例
    ES5
    在ES5中我们是使用匿名函数的函数作用域来当做块级作用域来使用的。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script>
        window.onload= function () {
            var aBtn = document.getElementsByTagName('input')
            for (var i = 0; i < aBtn.length; i++) {
                (function (i) {
                    aBtn[i].onclick = function () {
                        alert(i)
                    }
                })(i)
            }
        }
    </script>
</head>
<body>
    <input type="button" value="按钮1">
    <input type="button" value="按钮2">
    <input type="button" value="按钮3">
</body>
</html>

ES6
在ES6中,直接将变量声明var 改为let就解决了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script>
        window.onload= function () {
            var aBtn = document.getElementsByTagName('input')
            for (let i = 0; i < aBtn.length; i++) {
                aBtn[i].onclick = function () {
                    alert(i)
                }
            }
    </script>
</head>
<body>
    <input type="button" value="按钮1">
    <input type="button" value="按钮2">
    <input type="button" value="按钮3">
</body>
</html>


四、函数

1.函数-箭头函数

  • 箭头函数,就是函数的简写,可以用,可以选择不用。(我还是推荐用,主要是因为懒)
    • 如果只有一个参数,() 可以省
    • 如果只有一个return,{}可以省,return可以省
ES5:
	普通函数
	function name(){
		...
	}
	匿名函数
	function(){
	}

ES6:

去掉关键字function和函数名,使用=>连接参数列表和函数体。


	let name = () =>{
		....
	}

1.如果只有一个参数,() 可以省;没有参数,()不能省

	let show1 = function () {
    console.log('abc')
	}
	可以写成
	let show1 = () => {
	    console.log('abc')
	}


	let show2 = function(a){
		return a*2;
	}
	可以写成
	let show2 = a=>{
		return a*2;
	}

2.如果只有一个return,{}可以省,return可以省

	let show = function (a) {
	    return a*2
	}
	可以写成
	let show = a => a * 2

2.函数-参数

  • 参数扩展/展开 …args
    收集剩余的参数,必须当到最后一个参数位置
    展开数组,简写,效果和直接把数组的内容写在这儿一样

ES5:
ES5中我们使用函数中的类数组对象argments可以获取所有参数。


	如果要获取传入的多余参数,这如下。
	function show(a,b){
		for(var i=arguments.length-show.length-2,len=arguments.length;i<len; i++){
			console.log(arguments[i]);
		}
	}
	show(1,2,3,4,5,6,7);

ES6:
在参数列表中使用..args可以将多余的参数装入到数组args中,再使用..args就可以将数组展开。

ES6要获取传入的多余参数很简单,使用...args收集多余的参数
	function show(a, b, ...args) {
	    console.log(a)
	    console.log(b)
	    console.log(args)
	}
	console.log(show(1, 2, 3, 4, 5))	输出3,4,5
	
	参数展开
	let arr1 = [1, 2, 3]
	let arr2 = [4, 5, 6]
	let arr3 = [...arr1, ...arr2]
	console.log(arr3)

  • 默认参数
    给函数的参数设置默认参数。

ES5:

	function hello(txt){
		var str = txt || 'hello poorpenguin';
	}

ES6:

	function hello(txt='hello poorpenguin'){
	
	}

五、解构赋值

  • 解构赋值
    • 左右两个边结构必须一样
    • 右边必须是合法的
    • 声明和赋值赋值不能分开(必须在一句话里完成声明和赋值)

左右两个边结构必须一样

    let [a, b, c] = [1, 2, 3]
    console.log(a, b, c);			1 2 3
    
    let {x, y, z} = {x: 1, y: 2, z: 3}
    console.log(x, y, z);
	
	let [{a4, b2}, [num1, num2, num3], num4 ,str2] = [{ a4: 1, b2: 2 }, [1, 2, 3], 8, 'str'];
	console.log(a4, b2, num1, num2, num3, num4, str2);
    
    可以自行选择解析的粒度
    let [json, arr, num, str] = [{ a: 1, b: 2 }, [1, 2, 3], 8, 'str']
    console.log(json, arr, num, str);

	这样式错误的
	let [a,b] = {a:12,b:45};

在这里插入图片描述

右边必须是合法的

	这样式错误的
	let {a,b} = {12,5}

声明和赋值赋值不能分开,必须在一句话

	这种是错误的。
	let [a,b];
	[a,b] = [12,5];


六、数组

ES6中新增了4个数组的方法

  • map 映射(参考jquery中的map)
  • reduce 汇总
  • filter 过滤器
  • forEach 循环(迭代)

map 映射

可以遍历一个数组,对数组中的值进行操作,不改变原数组,并返回一个新数组。

  • 我给你10个,你就要返我10个

数组中的每一项都会作为回调函数的参数。使用return才可以将值返回给新数组。

例子1:

	let arr = [2,6,1,40];
	let newArr = arr.map(function(item){
		return item*3;
	});
	console.log(newArr);		
	输出[6, 18, 3, 120]
	
	可以使用ES6函数简写:
	let newArr = arr.map((item)=>item*3);

例子2:

	let score = [19,60,56,80,100];	学生成绩
	let result = score.map((item)=>item>=60?'及格':'不及格');
	console.log(result);
	和学生的成绩一一对应["不及格", "及格", "不及格", "及格", "及格"]

reduce 汇总

  • 汇总就是 一堆出来一个
    • 用于比如,算个总数,算个平均

例子1:求和

	var arr = [22,33,12,67,98];
	
	temp为回调函数中上一次的返回值,第一次temp的值为arr[0]
	item为数组项
	index为item的下标
	var result = arr.reduce(function(temp, item, index){
		return temp+item;
	});
	console.log(result);
	232

	ES6简写
	var result = arr.reduce((temp, item, index)=>temp+item);

例子2:求平均值
前几次都是求和,在最后一次才求平均值

	var arr = [22,33,12,67,98];
	var result = arr.reduce(function(temp, item, index){
		if(index!=arr.length-1){
			return temp+item;
		}else{	最后一次加完并求平均值
			return (temp+item)/arr.length-1;
		}
	});
	console.log(result);
	45.4

	ES6简写:
	var result = arr.reduce(
		(temp, item, index)=>(index!=arr.length-1)?temp+item:(temp+item)/arr.length-1
	);

filter 过滤器

通过回调函数return返回的值来决定值是否保留,true保留;false过滤掉。
不改变原数组,并返回一个新数组。

例子1:保留能被3整除的数

	let arr=[12,34,23,67,23,89,15];
	let result = arr.filter(item=>item%3==0);
	console.log(result);

例子2:商品价格过滤

	let arr=[
		{title: '男士衣服1', price:200},
		{title: '男士衣服2', price:240},
		{title: '女生衣服1', price:2000},
		{title: '女生衣服2', price:3000},
		{title: '女生衣服3', price:4000},
	];

	let result = arr.filter(item=>item.price<1000);
	console.log(result);

forEach 循环

forEach有两个参数,第二个参数是下标,可加可不加。

var arr = [32, 12, 45, 9];
var result = arr.forEach(item => console.log(item));
var result = arr.forEach((item, index)=>console.log(item, index));



七、字符串

  • ES6字符串新增两个方法
    • startsWith() 判断字符串以什么开头,是返回true,否返回false
    • endsWith() 判断字符串以什么结尾,是返回true,否返回false
  • 字符串模板(很重要)

1.新增方法startsWith()endsWith()

就是可判断字符串是否以规定的字符串开头和结尾。

例子1:判断网址是什么类型的
代替了之前使用正则判断。

	let str='https://www.baidu.com';
	if(str.startsWith('https://')){
		console.log('加密网址');
	}else if(str.startsWith('http://')){
		console.log('普通网址');
	}else if(str.startsWith('git://')){
		console.log('普通网址');
	}else if(str.startsWith('svn://')){
		console.log('普通网址');
	}

例子2:判断文件类型
根据扩展名。也是代替了正则判断。

	let str = 'test.txt';
	if(str.endsWith('.jpg')){
		console.log('图片文件');
	}else if(str..endsWith('.txt')){
		console.log('文本文件');
	}else{
		console.log('其他');
	}

2.字符串模板

该功能很强大,很好用。

  • 使用反引号(就是键盘1左边的那个)
  • 可以直接把变量的值塞到字符串里,${变量}
  • 可以折行
	let a = 12
	let str1 = `asdf${a}`
	console.log(str1)	
	输出asdf12

	let title = '标题'
	let content = '内容'
	let str = `<div>
	<h1>${title}</h1>
	<p>${content}</p>
	</div>
	`
	console.log(str)
	输出
	<div>
	<h1>标题</h1>
	<p>内容</p>


八、ES6面向对象

ES5
ES5的面向对象是没有类这个概念的。

	function Person(name,age){
		this.name=name||'未知';
		this.age=age||18;
	}
	Person.prototype.sayHello(){
		console.log('你好我是'+this.name);
	}

	var user = new Person('poorpenguin',25);
	user.sayHello();

ES6
而ES6中的面向对象很像java。

  • 使用关键字class
  • 使用constructor构造器
	class Person{
		构造函数
		constructor(name, age){	
			this.name=name||'未知';
			this.age=age||18;
		}
		
		方法
		sayHello(){
			console.log('你好我是'+this.name);
		}
	}
	var user = new Person('poorpenguin',25);
	user.sayHello();

继承

ES5中的继承其实就是各种方法凑合出来的,写起来脑壳疼。

ES6的继承更像java。

  • 使用extends继承。
  • 使用super调用父类(超类)构造器。
	class User{
		constructor(name, age){
			this.name = name;
			this.age = age;
		}
		sayHi(){
			console.log('你好,我是'+this.name);
		}
	}

	class VipUser extends User{
		constructor(name, age, level){
			super(name, age);
			this.level = level;
		}
		sayLevel(){
			console.log('vip等级'+this.level);
		}
	}

	var user = new VipUser('poorpenguin',25,3);
	user.sayHi();			你好,我是poorpenguin
	user.sayLevel();		vip等级3



九、json格式

json是一种格式,我们经常在js中写的对象就是json格式的。

1.json的转换的常用方法(ES5中就有的)

  • JSON.stringify() 将对象转为json字符串。
  • JSON.parse() 将json字符串转为对象。
    • 并不是所有字符串都可以转成json,json字符串的标准写法:
      1. {}中所有的key都必须用双引号包起来。
      2. {}中只能使用双引号。
	json字符串的正确格式
	var str1 = '{"a":12,"b":15,"c":"str"}';var str2 = '{a:12,b:15,c:"str"}';		×

	json——>字符串
	var str = 'hi,' + JSON.stringify(json)
	如果想要将json转为字符串作为参数,必须使用 encodeURIComponent()将json字符串进行编码
	var json = {a: 12, b: 5}
	var url = 'http://www.xx.com/' + encodeURIComponent(JSON.stringify(json))
	console.log(str)
	console.log(url)

	字符串——>json
	var str = '{"a": 12, "b": 4, "c": "abc"}'
	var json = JSON.parse(str)

json的简写

  • json对象中的方法可以去掉冒号:function
  • key和value 一样时可以简写
	var a = 12, b = 5
	var obj1 = {a:a,b:b};
	简写
	var obj1 = {a,b};
	
	
	var obj3 = {
		name: 'poorpenguin',
		age: 25,
		say: function(){
			console.log('hello world!');
		}
	}
	简写
	var obj3 = {
		name: 'poorpenguin',
		age: 25,
		say(){
			console.log('hello world!');
		}
	}




十、Promise

Promise就是异步解决方案,他是一个代理对象,和原先要进行的操作无关,使用它只是避免产生回调地狱。

1. Promise对象的状态

Promise对象有三种状态:

  • pending: [等待]或者进行中,表示还没有得到结果
  • fulfilled: [实现]操作成功,表示得到了我们想要的结果,可以继续往下执行
  • rejected: [被否决]操作失败,因此拒绝执行
  • Promise实例的状态一经改变,就无法在改变。
promise的基本写法

执行器中的代码在new Promise()时,就立即执行了。

	new Promise(
		//执行器
		function(resolve, reject){
			//异步操作
			if(数据处理结果){	成功
				resolve();
			}else{				失败
				reject();
			}
		}
	).then(function(){
		//成功,下一步
	},function(){
		//失败,相应处理
	});
pending

刚开始实例化Promise对象时,它的状态是pending。

fulfilled

当在执行器中调用resolve()时,Promise实例对象的状态被改为fulfilled。

rejected

当在执行器中调用reject()时,Promise实例的状态被改为rejected。


2. promise的执行顺序

Promise实例的状态发生改变,就会立即触发then()里对应的处理函数(回调函数)。
在这里插入图片描述


3. Promise的基本使用

	let p1 = new Promise(function(resolve, reject){
		使用setTimeout模拟异步操作
		setTimeout(function(){
			console.log('异步操作执行成功!');
			resolve('这是返回的数据');
		},2000);
	});

我们会发现在实例化promise对象的候秒钟,控制台就输出结果。但是我们并没有调用。
在这里插入图片描述
所以建议使用函数将new Promise包裹起来并return promise实例化出来的对象,需要的时候再调用。

	function run(){
		let p1 = new Promise(function(resolve, reject){
			//使用setTimeout模拟异步操作
			setTimeout(function(){
				console.log('异步操作执行成功!');
				if(true){
					resolve('这是返回的数据');
				}else{
					reject();
				}
			},2000);
		});
		return p1;
	}
	
	run().then(function(data){
		console.log('对'+data+'做了其他操作');
	},function(data){
		
	});

2秒后,对返回的数据进行其他操作。
在这里插入图片描述


4. then() 的链式操作

  • then()接收两个函数作为参数,分别代表fulfilled和rejected两个状态的响应函数
  • then() 返回一个新的Promise实例,所以可以链式调用。
  • 前面的promise实例状态改变时,then()会根据最终状态,调用特定的响应函数。(不管哪一级的then()都遵循)

then()的返回值的三种情况:

  • return 新的promise。下一级then()等待return 新的promise 状态改变后再根据状态执行。
    then()本身确实会返回一个(原)promise,但是如果不手动return (新)Promise,那么默认返回的(原)promise状态就是resolved
	function run(){
		let p1 = new Promise(function(resolve, reject){
			setTimeout(function(){
				console.log('异步执行完成!');
				if(true){
					resolve(1);
				}else{
					reject();
				}
			},2000);
		});
		return p1;
	}


	run().then(function(data){
		console.log('获得'+data+',并作为数据执行下一步');
		return new Promise(function(resolve, reject){
			if(data == 1){
				resolve(2);
			}
		});
	}).then(function(data){
		console.log('获得'+data+',并作为数据执行下一步');
		return new Promise(function(resolve, reject){
			if(data == 2){
				resolve(3);
			}
		});
	}).then(function(data){
		console.log('获得'+data+',结束');
	});
  • then()中没有return。下一个then()得到的值就是underfined
	function run(){
		let p1 = new Promise(function(resolve, reject){
			setTimeout(function(){
				console.log('异步执行完成!');
				if(true){
					resolve(1);
				}else{
					reject();
				}
			},2000);
		});
		return p1;
	}
	
	run().then(function(data){
		console.log(data);				1
	}).then(function(data){
		console.log(data);				underfined
	})
  • return非promise。那么值就是这个非promise。
	function run(){
		let p1 = new Promise(function(resolve, reject){
			setTimeout(function(){
				console.log('异步执行完成!');
				if(true){
					resolve(1);
				}else{
					reject();
				}
			},2000);
		});
		return p1;
	}
	
	run().then(function(data){
		console.log('1');
		return 'poorpenguin';			
	}).then(function(data){
		console.log('2');
		return data;				
	}).then(function(data){
		console.log('3');
		console.log(data);		poorpenguin
	});

5. Promise.all()

  • Promise.all([p1,p2,p3…]) (p1、p2、p3…都是promise实例)用于将多个Promise实例,包装成一个新的Promise实例。
  • 接收一个数组作为参数。
  • 当所有子Promise成功时,父promise的状态才为fulfilled。
	var promise = Promise.all( [p1, p2, p3] )
	promise.then(
	    ...
	).catch(
	    ...
	)

当p1、p2、p3的状态都变成fulfilled时,父promise才会变成fulfilled,并调用then()的已完成回调,但只要有一个子promise变成rejected状态,父promise就会立刻变成rejected状态


6. Promise.race()

和Promise.all()差不多,很少用。
只要有一个子Promise状态变成fulfilled时,父promise的状态就为fulfilled。


7. 高版本jquery(3.0以上)自带promise支持

$.ajax()的返回值就是Promise实例

let promise = $.ajax({url:'.....',dataType: 'json'});

所以

	Promise.all([
		$.ajax({url:'.....',dataType: 'json'}).
		$.ajax({url:'.....',dataType: 'json'}),
		$.ajax({url:'.....',dataType: 'json'}),
	]).then(function(data){
		let [arr1, arr2, arr3] = data;
		console.log(arr1, arr2, arr3);
	});
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值