ES6

Q1.什么是ES6

ES6是ECMAScript的第六代版本

此前ECMAScript的历史
1996     ES1.0 (Netscape公司将js交给了ECMA组织 ES1.0正式面世)
1998     ES2.0
1999     ES3.0
2007     ES4.0(因为过于激进的改动和更新导致开发者不认同4.0版本,因此废除4.0版本)
2008     ES3.1(对ES4.0经过一年的完善和压缩,形成了现在使用最多的一个版本ES3.1(别称ECHarmony))
2009     ES5.0(在面世时就已经拟定的ES6.0的草案)
2013     ES6.0(ES6.0的草案完成)
2013.12     ES6.0(ES6.0的草案发布)
2015.06     ES6.0(ES6.0的正式发布)ES6如此繁琐的开发过程是为了避免ES4.0版本激进开发的错误
2016     ES7(从16年开始就不再使用旧版本号,而是以年份代号)
2017     ES8
2018     ES9

Q2.ECMAScript与JavaScript的关系

ECMAScript是一个编程语言的标准
JavaScript是实现这个编程语言的标准

JavaScript是由ECMAScript+WEBapi(DOM、BOM)组成的
flash是由actionScript+WEBapi(DOM、BOM)组成的 (已淘汰

Q3.怎样学习ES6

将ES3.1写法与现在ES6写法相对比学习,思考有什么不同,会有什么样的优化

提供工具:Babel

Q4.ES6有什么用

新增了许多语法规范,可以对写法和开发有很大的帮助

但对技术上的提升较小

Q5.浏览器有几条线程

浏览器有5条线程

1.js线程(主线程)负责去执行栈顶代码
2.GUI线程
3.事件监听线程(负责监听各种事件)
4.计时线程(负责定时器)
5.网络线程(各种网路请求)



ES6语法

let

声明变量
ES3.1声明变量方式 //var num = 100(直接挂再window上。容易造成全局污染)
ES6声明变量方式 //letnum = 100(不会造成全局污染)
let不允许重复声明
let不会有声明提前
在人为效果上是没有声明提前,而实则将数据保存到临时性死区中

Cannot access 'num' before initialization
//出现这种错误时表式将数据保存到临时性死区

{}

块级作用域
ES3.1局部作用域

(function(){
	var num = 100;//通过匿名函数创建局部作用域
})()

ES6块级作用域

{
	var num = 100;//与局部zuo'yong
}

const

常量声明
const不允许重复声明
const不会有声明提前
且常量不允许改变值

//实则是不允许改变内存空间的地址。
const obj={};
obj.name =  "jack"
console.log(obj)//{name:jack}
//const声明和赋值必须一次性完成,并且后期不允许改变存储空间地址
const abc;
abc = 123;
console.log(abc)//报错,

字符串

字符串的换行
ES3.1 //var str = “asd\n\asasa”
ES6 //let str = `asdasasa`

字符串的拼接(可以添加转义字符,可以嵌套)
ES3.1 //conslog.log(str + date + "asdsd")
ES6 //conslog.log(`${变量/表达式}asdasad`)

解构

结构化赋值,可以简写书写长度,提升效率

//对象的解构
let obj = {
		 	name : "jack",
		 	age : 18,
		 	sex : "nan",
		 	class : 10
		 }
		  let {name ,age,sex,class} = obj;
		  console.log(name ,age,sex,class);
		  
//数组的解构
let arr=[1,2,3,4]
		  let[q,w,e,r] = arr;
		  console.log(q,w,e,r);
//数组的解构获取长度
		  let{length}= arr;
		  console.log(length);
数组赋值
//(ES3.1)
		   var a = arr[1]
		   var b = arr[0]		
		   var c = arr[4]
		   var d = arr[3]
//(ES6)
		   let {1:a,0:b,4:c,3:d} = arr;	//2,1,10,4	   

…运算符

1.收集符只能出现一次
2.收集符只能在参数的最后一个形参
收集功能

//(ES3.1)
function sum(){
		 	console.log(arguments.push(6))  //报错,arguments是一个类数组,不能添加
		 }
		 sum(1,2,3,4,5)
//(ES6)
function sum(a,b...arg){   //收集参数只能放在最后一个参数
		    arg.push(6)//添加
		 	console.log(a,b,arg)
		 }
		 sum(1,2,3,4,5)		

展开

  ES6(数组),
   // 拼接
	let arr = [1,2,3];
	console.log(...arr);
	let arr2 = [4,5,6];
	let newArr = [...arr,...arr2];
	console.log(newArr)

   //克隆
	let arr1 = [1,2,3,4,{name:"jack"}];
	let arr2 = [...arr1];
	console.log(arr1 == arr2);//false这是两个不同的数组
	console.log(arr1[4] == arr2[4]);  //true 只克隆了值而没有克隆地址称为浅克隆
	
	ES7(object)
	let company = {
		name : "bailiban",
		age : 16
	};
	let leader = {
		name : "peng",
		age : 18
	}
	let teachDepartment = {
		leader : {
			...leader
		},
		personNum : 20,
		data : [new Date()]
	};

函数

function fun(a,b,c){//当用户想输出a=0时必须进行处理
			// a = 10;
			// b = 20;
			//ab为固定值// c是任意值 // 绝大数情况
			// a = a || 10;
			// b = b || 20;//输出为60
			a = a === undefined && 10;//通过这样处理可以传递a = 0;
			b = b === undefined && 20;
			return a + b + c;
}
console.log( fun(0,0,30) )  //用户想传递a = 0;

ES6参数可以加默认值(new)

function fun(a,b=10,c=20){
	return a+b+c;
		console.log( fun(undefined,undefined,30) );//60
		console.log( fun(1,2,3) )//6
		console.log( fun(30) )//60,将默认值写在后面,可以直接传一个数
		console.log( fun(10,undefined,30) )//50
		console.log( fun(10,null,30) )   //40,null在数学中,默认的为0,不要传递null
}

ES6可以传递表达式(new)
× 不能传递语句 ×

		//ES3.1创建一个元素  插入到某个元素中 
		// name 创建的标签   大多数为div
		// container  需要往哪个元素中插入   大多数为container
		// content   内容

		function createElement(name,container,content){
			const ele = document.createElement(name);
			if(content){
				ele.innerHTML = content
			}
			container.appendChild(ele)
		}
	createElement("div",document.getElementById("container"),"sdfsdfsd")
	//成功,在页面中插入div内容为sdfsdfsd
	
		//ES6创建一个元素  插入到某个元素中
							   				//ES6可以在参数中传递表达式
		function createElement(name = "div",container = document.getElementById("container"),content){
			const ele = document.createElement(name);
			if(content){
				ele.innerHTML = content
			}
			container.appendChild(ele)
		} 
	createElement(undefined,undefined,"sdfsdfsd")//成功,在页面中插入div内容为sdfsdfsd
	
函数>arguments

arguments在严格模式中arguments和函数的形参不存在关系,没有对应的映射关系
! 只要给函数加上了参数默认值,该函数会自动变成严格模式 !
!形参和let,const一样,有自己的作用域,根据声明的顺序会产生生临时性死区 !

//已自动开启严格模式
function test(a,b=10){
			console.log("arguments",arguments[0],arguments[1])//arguments 1 2
			console.log('a',a,"b",b)//a 1 b 2
			a = 5;
			console.log("arguments",arguments[0],arguments[1])//arguments 1 2
			console.log('a',a,"b",b)//a 5 b 2
		}
		test(1,2)					   
函数>new.target(new)
	//ES6以前
	function Person(firstName,lastName){
	if(!(this instanceof Person)){
		throw new Error("该函数必须使用new调用")//这样就可以在直接调用下提示错误
												//但这样是无法完全避免的
	}
		this.firstName = firstName;
		this.lastName = lastName;
		this.fullName = `${firstName} ${lastName}`
	}
//面试点:new调用和直接调用结果
//new调用
const p1 = new Person("张","三")
console.log(p1)//成功调用
//直接调用
const p2 =  Person("张","三")
console.log(p2)//失败undefined
//通过call改变指向依然会undefined
const p3 = Person.call(p1,"张","三")
console.log(p3)

//ES6
//使用new.target就可以真正避免此问题
if(new.target === undefined){//如果没有使用new 关键字调用函数,则返回undefined
	throw new Error("该函数必须使用new调用")//如果使用了new调用,则返回的是函数的本身
}

函数>箭头函数

箭头函数是一个函数表达式,理论上任何使用函数表达式的地方都可以改成箭头函数
(参数1,参数2…)=>{函数体}

this指向问题
1.对象调用函数,this指向对象
2.直接调用函数,this指向window
3.如果使用了new关键字,this指向新创建的对象
4.如果使用apply,call,bind this指向绑定的数据
5.如果是DOM事件函数,this指向事件源

箭头函数语法
// 箭头函数的写法
		// 简写
		// 1.如果参数只有一个,可以省略小括号
		// 参数 => {}
		const print = num => {
			console.log(num)
		}
		print(1000)
		// 2.如果箭头函数只有一条返回语句,可以省略花括号,可以省略return
		// 参数 => 返回值
		const isOdd = function(num){
			return num % 2 !== 0;
		}
		const isOdd = num => {
			return num % 2 !== 0;
		}
		const isOdd = num => num % 2 !== 0;
		console.log(isOdd(3))
		console.log(isOdd(4))
		// 2.1 如果返回值是一个对象的时候
		const obj = (a,b) => 
			({//只有花括号就会认为成函数体就会报错//把返回值变成表达式的形式就ok
				a : a,
				b : b
			})
		console.log( obj(1,2) )
		//面试点
		// 1.箭头函数中没有this,argument,new.target,如果要强行使用,则指向函数外层对应的this,argument,new.target
		// 2.箭头函数没有原型,所有说占用空间非常小,不能当成构造函数来使用
		console.log(func,func.prototype)   
		console.dir(func)
		// 应用场景
		// 1.临时使用的函数,并不会刻意的去调用
			// 1.异步的处理函数
			// 2.事件的处理
		// 2.继续去沿用外层的this
		// 3.对象的属性不要去用箭头函数,除非是特别的需求
		// 4.数组方法的时候,保证代码的简洁
		const arr = [1,2,89,45,123,54];
		const result = arr.map(num => num*2);
		console.log(result)

对象

1.成员速写

{											{
	loginId:loginId,							loginId,	
	loginPwd:loginPwd,		---->				loginPwd,
	nickName:nickName,							nickName,
}											}
//属性名和属性值相等的时候可以使用ES6成员速写

2.方法速写

3.计算属性名

const prop1 = "name";   //我们不知道属性名是什么,由后台返回给你的
		const prop2 = "age";
		const prop3 = "say"
		const user = {
			[prop1] : "尹老师",
			[prop2] : 30,
			[prop3](){
				console.log(this[prop1],this[prop2])
			}
		}
		console.log(user[prop1])
		user[prop3]()

4对象的API

1.is()相等于===
语法:Object.is(值,值)//返回true/false
2.assign()  用于混合对象,带浅克隆   ...ES7
 const obj1 = {
			a : 123,
			b : 456,
			c : "abc"
		}
		const obj2 = {
			a : 789,
			e : "asdf"
		}
		const obj = Object.assign(obj1,obj2)// 将2的内容覆盖到1 
		console.log(obj == obj1)//true
3..getOwnPropertyNames()  枚举的顺序,返回一个数组,枚举出来对象的属性
		 // 先排数字,升序// 再排其他,按照书写顺序
	const obj = {
			e : 1,
			a : 2,
			c : 3,
			0 : 6,
			5 : 7,
			2 : 3
		}
		console.log(obj)
		const arr = Object.getOwnPropertyNames(obj);
4. setPrototypeOf()  设置某个对象的隐式原型 __proto__  
const obj1 = {
			a : 1
		}
		const obj2 = {
			b : 2
		}
		// obj1.__proto__ = obj2   必须要通过构造函数来完成
		Object.setPrototypeOf(obj1,obj2)
		console.log(obj1)

构造函数
ES3.1缺点:属性和原型方法分开了,代码可读性差
ES6优点:从逻辑上说更合理,成为一个整体
ES6构造函数规范
1.类的声明不会被提升,和let const 一样,有临时性死区
2.类的所有代码全都是在严格模式中执行
3.类的所有方法都是不可枚举的
4.类的所有方法都无法当成构造函数直接使用
5.类的构造器必须使用new 来调用
对象中类的方法
1.可以写成计算属性名
2.可以使用getter 和 setter×暂未理解×
3.静态成员×暂未理解×
4.字段初始器(es7)

class Test{
			a = 1;  //简写,初始化的工作,如果没有使用static,就是实例成员
			b = 2;
			static c = 3
			// constructor(){
			// 	this.a = 1;
			// 	this.b = 2
			// }
			const t = new Test()
			console.log(t.a,t.b,t.c,Test.c)//1,2,ubdefined,3
  1. 类表达式
const A = class{   //匿名类,类表达式,类在js中本身就是表达式
			a = 1;
			b = 2;
		}
		const a = new A();
		console.log(a)
//ES3.1构造函数
function Person(job,name,age,sex){
			this.job = job;
			this.name = name;
			this.age = age;
			this.sex = sex;
		}
		//增加实例方法
		Person.prototype.print = function(){
			console.log('工作:',this.job)
			console.log('姓名:',this.name)
			console.log('年龄:',this.age)
			console.log('性别:',this.sex)
		}
		const a = new Person("程序猿","zhansan",30,"nan");
		a.print()
//ES6构造函数
class Person{
			constructor(job,name,age,sex){
				this.job = job;
				this.name = name;
				this.age = age;
				this.sex = sex;
			}
			print(){
				console.log('工作:',this.job)
				console.log('姓名:',this.name)
				console.log('年龄:',this.age)
				console.log('性别:',this.sex)
			}
		}
		const a = new Person("程序猿","zhansan",30,"nan");
		console.log(a)
		a.print()

原型链(暂不理解)

符号

symbol(符号描述)来创建的
语法:const syb =symbol(参数为符号的描述);
作用:符号的设计,给对象去新增私有属性,只能在内部进行访问,外部无法使用
符号的特点
1.没有字面量的写法
2.symbol是在ES6中的一种数据类型(new)
3.每次调用symbol函数得到的符号永远不会相等,不管符号描述是否相同
4.符号可以作为对象的属性名使用,这种属性名叫符号属性
5.可以通过设计,让外面无法访问到
6.符号属性不能被枚举(针对符号特殊属性getOwnPropertySymbols(obj))
7.符号类型无法被隐式转换,数字运算,字符串拼接都是不行的
可以进行内部的显示转换
8.共享符号Symbol.for(“符号描述”) 如果符号描述相等,则可以得到同一个符号

const syb2 = Symbol.for("abc");
		console.log(syb1,syb2)
		console.log(syb1 === syb2)
		const obj = {
			a : 1,
			b : 2,
			[Symbol.for("c")] : 3
		}
		console.log(obj)
		console.log(obj[Symbol.for("c")])

执行栈()

call stack 一个数据结构,存放各种函数执行环境每一个函数执行之前,它的相关信息会加入执行栈函数调用完成,会销毁执行栈
js引擎会永远执行栈顶。执行栈的最顶部
js是单线程。

面试题

i值问题

//要求点击对应的按钮弹出对应的数据
	<button>0</button>
	<button>1</button>
	<button>2</button>
	<button>3</button>
	<button>4</button>
	<button>5</button>
	<button>6</button>
	<button>7</button>
	<button>8</button>
	<button>9</button>
<script>
//ES3.1(有且只有一种)(包裹一个函数产生作用域)
	var buttons = document.getElementsByTagName("button");
		for(var i = 0;i < buttons.length;i++){
		(function(i){
			buttons[i].onclick = function(){
				console.log(i);
			}
			})(i)
		}
//ES6
var buttons = document.getElementsByTagName("button");
		for(let i = 0;i < buttons.length;i++){
			buttons[i].onclick = function(){
				console.log(i);
		}
</script>

let解决闭包的问题

 //控制台有什么内容,怎样改动才可以输出0123456789
		var arr = [];
		for(var i = 0;i<10;i++){
	     		arr[i] = function(){
					console.log(i);
				}
		 }
		arr[0]()
		arr[1]()
		arr[2]()
		arr[3]()
		arr[4]()
		arr[5]()
		arr[6]()
		arr[7]()
		arr[8]()
		arr[9]()
		console.log(i)
		//实际上这个问题分成两问
		//1.是输出数组0-9这个比较简单,在开始循环中将var i 改成 let i 即可
		//2.输出这i这个才是个掉坑的地方,当你将开始循环中将var i 改成 let i之后{}形成了一个块级作用域,
		//再想输出i是就会报错
//解决方法添加立即执行函数
		var arr = [];
		for(var i = 0;i<10;i++){
	     		(function(i){
		 		arr[i] = function(){
		 			console.log(i);
		 		}
		 	})(i)
		 }
		arr[0]()
		arr[1]()
		arr[2]()
		arr[3]()
		arr[4]()
		arr[5]()
		arr[6]()
		arr[7]()
		arr[8]()
		arr[9]()
		console.log(i)

…运算符计算平均值

//计算平局值
		function computedScore(...arg){
			// console.log(arg)
			let sum = 0;
			arg.forEach(function(ele){
				sum +=ele
			})
			return sum / arg.length;
		}
		console.log(computedScore(97,99,93,92,90,81,88,70))
//去掉一个最高分,去掉一个最低分
		function average(...arg){
			arg.sort(function(a,b){
				return a-b;
			})
			// console.log(arg)
			arg.pop();
			arg.shift();
			// return computedScore.apply(this,arg);
			return computedScore(...arg);
		}
		console.log(average(97,99,93,92,90,81,88,70))

ES6函数传递表达式面试题

function getContainer(){
			console.log('test');
			return document.getElementById("container")
		}
		// 控制台输出几次test?
		createElement(undefined,undefined,"sdfsdfsd")
		createElement(undefined,undefined,"sdfsdfsd")
		createElement(undefined,document.getElementById("container"),"sdfsdfsd")  
								// 2次  传递以后不会去看默认值的

ES6函数临时性死区面试点

function test(a=b,b){//因为没有声明b而提前使用b就会造成临时性死区//(a,b=a)  
			console.log(a,b)
		}
		test(undefined,2)//报错

查看函数有多少次入栈出栈操作

function a(){
			console.log('a');
			b()
		}
		function b(){
			console.log('b');
			c();
		}
		function c(){
			console.log('c');
		}
		console.log('global');
		a()

扩展

 //深克隆   会存在问题   对引用值直接转化,不推荐使用
 		//jqury.api
		let obj2 = JSON.parse(JSON.stringify(teachDepartment));
		obj2.leader.name = "yin";
		console.log(teachDepartment)
		console.log(obj2)


		
		$.extend() //抄袭jquery  
		assign({},,,,,,)   //浅克隆
		let obj = Object.assign({"asdf":"asdfsdf"},company,teachDepartment);
		console.log(obj)
// 知名符号
// 特殊含义的共享符号   通过Symbol的配置得到的
// JavaScript 松散,写法不严谨
// 必须去解决这些严谨性的问题
// 配置底层的实现原理
// console.log(A[Symbol.hasInstance](obj));  //不能这种方式配置
		Object.defineProperty(A,Symbol.hasInstance,{
			value : function(obj){
				console.log(obj);
				return false;
			}
		})
		const obj = new A();
		console.log(obj instanceof A)    //可以去改变instanceof  的值
		//2.Symbol.isConcatSpreadable   会对数组的方法产生影响
		const arr = [3];
		const arr2 = [4,5,6,7]
		arr2[Symbol.isConcatSpreadable] = false;
		const result = arr.concat(99,arr2)   //对两个数组拆分链接成新的数组
		console.log(result)
		const arr = [1];
		const obj = {
			0 : 3,
			1 : 5,
			length : 2,
			[Symbol.isConcatSpreadable] : true
		}
		const result = arr.concat(99,obj)
		console.log(result)
		//3.Symbol.toPrimitive
		const obj = {
			a : 1,
			b : 2
		}
		obj[Symbol.toPrimitive] = function(){
			return 123
		}
		console.log(obj + 123)
		// 4.Symbol.toStringTag  可以影响Object.prototype.toString的返回值
		class Person{
			[Symbol.toStringTag] = "Person"
		}
		const p = new Person()
		console.log(p)
		const arr = [12,1,2]
		console.log(Object.prototype.toString.call(p))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值