JavaScript笔记——ES6新增语法篇

ES6过渡史

ES:ECMAJavaScript的缩写
babel 转译器,将ES6–> ES5

JavaScript笔记——ES6新增语法篇_第1张图片
JavaScript笔记——ES6新增语法篇_第2张图片
2. traceur

块级作用域与嵌套、let、暂行性死区

  1. kiss原则:keep it simple,stupid

1. 块级作用域

JavaScript笔记——ES6新增语法篇_第3张图片

2. let 关键字

声明的变量具有块级作用域,类似 { }

2.1 let声明的变量只在所处于的块级有效(可以防止循环变量变成全局变量)
if(true){
     
	let a=10;
}
console.log(a);// a is not defined	

JavaScript笔记——ES6新增语法篇_第4张图片

2.2 不存在变量提升,因此在此之前不能使用let值,且在此之前的位置叫做暂时性死区(不能提升的这部分区域叫做暂时性死区)
console.log(a); // a is not defined
let a=20;

简单而又怪异的题目:

var a = a;
console.log(a);  // undefined


let b = b; // b在没有赋值之前就引用了,而这是一个死区 (这个是自右向左执行的欸!把b赋值给b,而又因为b还没定义,所以报错)
console.log(b); // 报错

//===============================
function test(x = y,y = 2){
     
	console.log(x,y); // 报错,因为这依然是个死区。它将y赋值给x,但是y还没有被定义
}

typeof有可能会报错了

console.log(typeof a); // 报错
let a;

ES6语法:能够在函数的参数进行赋值,给它默认值

2.3 暂时性死区

就是,在块级作用域中,使用let声明变量,这个变量会与这个块级整体进行绑定,不受外部影响。

var num=10;
if(true){
     
	console.log(num); //会报错,num is not defined
	let num=20;
}

2.4 在同一作用域下不能重复声明

(同一作用域:块级作用域、全局作用域、函数作用域)

例子:

function test(a){
     
	let a = 10;
	console.log(a); //报错了,形参处定义了a
}

test();

//===============================
function test(a){
     
	{
     
		let a = 10;
	}
	console.log(a); //undefined
}

test();


for(var i = 0; i < 10; i++){
     
	 i = 'a'; 
	console.log(i);
}

打印出1个a,分析:

var i = 0;

for( i < 10; ){
     
	i = 'a'; // 被重新赋值了
	console.log(i); // 'a'
	i++; //'a1'
}
//-----------------------------------------
for(var i = 0; i < 10; i++){
     
	var i = 'a';
	console.log(i);
}

打印出1个a,分析:

var i = 0;

for( i < 10; ){
     
	var i = 'a'; // 被重新赋值了
	console.log(i); // 'a'
	i++; //'a1'
}
  • let 用 for循环执行的时候有一个父子作用域的问题

”表达式也是一块作用域“

情况:


for(let i = 0; i < 10;i++){
     
	 i = 'a';
	console.log(i); // 打印出1个a
	 
}

分析:
{
     	
	let i = 0; 
	{
     
		// ① 子级作用域可以使用父级作用域中的变量
		// ② 因为子级里头没有嘛,所以他拿了父子的,并更改为'a'
		// 再执行i++ 的时候就变为 'a1'
		i = 'a';
	}
}

情况:


for(let i = 0; i < 10; i++){
     
	var i = 'a';
	console.log(i); // 报错
}

分析:
{
     
	var i; // 变量提升
	let i = 0; // 相当于声明了两次,所以会报错
	{
     
		var i = 'a';
	}
}

情况:


for(let i = 0; i < 10; i++){
     
	let i = 'a';
	console.log(i); // 打印出10个a
}

分析:
{
     
	
	let i = 0; // 相当于声明了两次,所以会报错
	{
     
		let i = 'a';
	}
}

打印 0-9 的情况:重新覆盖

var arr = [];

for(var i = 0; i < 10; i++){
     
	arr[i] = function(){
     
		console.log(i);
	}
	//到最后 i = 10;
}

// 但因为此处重新声明了一次,所以i被覆盖了
for(var i = 0; i < 10; i++){
     
	arr[i]();
}

区分:
JavaScript笔记——ES6新增语法篇_第5张图片

函数声明只能在顶层作用域和函数作用域当中

函数声明提升是在当前作用域基础上的

const、全部变量与顶层对象

1.2 const 关键字

作用:声明常量。内存地址不能变化的量
(简单数据类型的值是不能变化的,遇上复杂数据类型时只可改里头的内容,“保证指针不变”)

  • 具有块级作用域,也存在暂时性死区、不能提升、与let一样不能重复声明
  • 声明常量时必需赋值
  • 常量赋值后,值不可以修改(修改了会报错)

顶层对象

顶层对象——window
(不同的环境中顶层对象是会不一样的)

函数默认值、解构赋值、数组解构、对象解构

1. 函数默认值

对于ES5:

传入实参0,会被读成布尔值,这样就体现不了0了。因此这种方式在一些情况下就不合适


function foo(x,y){
     
	x = x || 1;
	y = y || 2;
	console.log(x+y);
}

foo(); // 3
foo(5,6); // 11
foo(5); // 7
foo(null,6); // 7
foo(0,5); // 6


“参数可以赋值” (待完善)

参数可赋值,那就可以传变量,那参数的作用域是怎样的?(默认值作用域问题)

可以理解为它是 let声明的

JavaScript笔记——ES6新增语法篇_第6张图片
JavaScript笔记——ES6新增语法篇_第7张图片
惰性求值: 函数的参数为表达式的情况下,参数加载的方式是惰性求值的方式,每(执行)一次都要重新计算表达式的值

2. 解构赋值

  • 解构失败:变量多了,没有“匹配”到的就是undefined

  • 不完全解构: 值多了

解构赋值中依然可以给默认值,给值了就不会找默认值

2.1 数组解构

  • 数组的解构存在顺序

关于数组解构例子:

let [a = 6] = [];
console.log(a);		// 6


// 浏览器默认undefined为没有赋值
let [a,b = 6] = [1,undefined];
console.log(a,b);		// 1, 6 

let [a,b = 6] = [1,null];
console.log(a,b);		// 1, null



let b = 5;
let [b = 6, c = b] = [];

console.log(b,c);		// 报错,b已经被定义了 

let [x = y, y = 1] = [];
console.log(x,y); // 报错,暂时性死区问题

2.2 对象解构

JavaScript笔记——ES6新增语法篇_第8张图片
对象的属性还能拼接:

let firstName = 'Xing';
let secondName = 'is';
let name = 'Xing is';
let person = {
     
	[firstName + secondName] : name
}

console.log(person);

对象的解构是不存在顺序的,是根据属性名来“匹配”的

JavaScript笔记——ES6新增语法篇_第9张图片
▲:对象解构还需要捂一捂

隐式转换、函数参数解构、解构本质、()用法


()用法

JavaScript笔记——ES6新增语法篇_第10张图片
解决:加一个括号,让大括号不再是作用域,而是表达式(如下)

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

  • 用 let / var 声明,加括号就报错
    (所以,定义参数的方式中间不能加括号)
    JavaScript笔记——ES6新增语法篇_第11张图片

数组也是特殊的对象,也能进行解构赋值

let  arr = [1,2,4];
let {
     0: first, [arr.length - 1]:last} = arr;

console.log(first,last);

[(b)] = [3]; // 这样可以匹配成功
console.log(b); // 3 

([b]) = [3];
console.log(b); // 不能成功,因为匹配的规则不一样,左边是表达式,右边是数组

({
     a: (b) = {
     }}); // 本身并没有匹配,这个是默认值
// 对象下面有个属性,属性默认值为{}
console.log(b); // {}

JavaScript笔记——ES6新增语法篇_第12张图片
模式匹配:
首先要模式一样才能进行匹配
其次,有括号的时候一定要注意 这括号起的是什么作用

模式匹配,本质上是声明变量

函数传参也相当于一个变量的声明,声明的方式是通过let来声明的

JavaScript笔记——ES6新增语法篇_第13张图片
JavaScript笔记——ES6新增语法篇_第14张图片

函数参数解构


计算属性解构:

模式匹配可以匹配同源属性(同一个源属性)

var x = 200, 
	y = 300, 
	z = 100;

var obj1 = {
     
	x: {
     
		y: 42
	},
	z: {
     
		y: z   // 这个z是多少哇?
	}
};

({
     y: x = {
     y: y}} = obj1); // obj1中没有y这个属性。所以就默认值

({
     z: y = {
     y: z}} = obj1);  //100

({
     x: z = {
     y: x}} = obj1); 

console.log(x.y, y.y, z.y); 


function foo({
     x = 10} = {
     }, {
     y} = {
     y: 10}){
     
	console.log(x, y);
}

foo(); // 10 10
foo({
     },{
     }); // 10 undefined;
foo({
     x: 2}, {
     y: 3}); // 2 3


注意:

({
     x = 10} = {
     }); ==>({
     x: x = 10} = {
     });

({
     y} = {
     y: 10}); ==> {
     y: y} = {
     y: 10}


解构隐式转换

转成类数组了:

const [a, b, c, d, e] = 'hello';

console.log(a, b, c, d, e); // h,e,l,l,o

let {
     length : len} = 'hello'; // 转成类数组了,类数组具有length属性
console.log(len); // 5 解构出来了就表示隐式转换

数字 对应的包装类 Num

let {
     toString: s} = 123;
console.log(s === Number.prototype.toString); // true

布尔值 对应的包装类 Boolean

let {
     toString: s} = false;
console.log(s === Boolean.prototype.toString); // true

undefined 和 null 都没有隐式转换

let {
     prop} = undefined;
console.log(prop); // 报错

let {
     prop} = null;
console.log(prop); // 报错

这也是为什么调用函数时不传内容会报错,是因为空的内容并不能进行隐式转换
JavaScript笔记——ES6新增语法篇_第15张图片


this指向、箭头函数基本形式、rest运算符

函数参数给了默认值的时候:

  • 会让函数的length发生变化
    变化依据:根据当前默认值的位置,只计算默认值前面的形参。
    像这样:
function test(a, b, c = 1, d, e, f){
     

}

tset();
console.log(test.length); // 2
  • 有arguments,但arguments的映射关系不存在了

回顾this指向

1. 默认绑定规则

  • 普通函数指向的是window
  • 立即执行函数的this 指向 window
  • 定时器指向的是window

2. 隐式绑定:谁调用,指向谁

JavaScript笔记——ES6新增语法篇_第16张图片

3. 显示绑定:call、apply、bind

4. new (优先级最高)

箭头函数(表达式)

格式:

( ) => {
      } 
const fn = ( ) => {
      }

如何调用?
赋值给一个变量

  • 如果形参只有一个,可以省略小括号
  • 如果函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
  • 箭头函数不绑定this关键字,this指向的是函数定义位置的上下文this

箭头函数可以和解构赋值结合来用
JavaScript笔记——ES6新增语法篇_第17张图片
在箭头函数中不存在arguments (侧面说明,箭头函数不是用function来声明的)

(…)spread / rest运算符 (展开或收集)

1. spread 扩展运算符

作用:

  1. 可以将数组或者对象转为用逗号分隔的参数序列 (展开)
  2. 可以用于合并数组
let ary1 = [1,2,3];
let ary2 = [4,5,6];
let ary3 = [...ary1,...ary2];

//或 ary1.push(...ary2);
  1. 将 类(伪)数组或对象转换为真正的数组
let divs = document.getElementsByTagName('div');
divs=[...divs];

2. rest运算符——收集

JavaScript笔记——ES6新增语法篇_第18张图片
在这里插入图片描述(反问 = 返回)


箭头函数的实质、箭头函数的使用场景

1. 当箭头函数只执行一条,且想返回一个对象的时候(用括号把它包起来)

(a,b) => ({
     a:3, b:4})

不是用function来定义的,是用胖箭头来定义的

  1. this,根据函数定义位置的上下文this (外层函数)来决定的;
    箭头函数的this 是不能用call的方式来指定的

this指向是固定化的,函数的内部并没有自己的this,只能通过父级作用域来获取到this,闭包的this

例1:

function fn(){
     
	return (a) => {
     
		console.log(this.a);
	}
}


var obj1 = {
     a: 2};
var obj2 = {
     a: 3};
var bar = fn.call(obj1); 
var bara = fn();
bar.call(obj2); // 2 (这样不会更改this指向,还是根据外层函数的this)
bar.call(obj2); // undefined 

例2:▲!注意理解这个

const person = {
     
	eat(){
     
		console.log(this);
	}
	drink:() => {
     
		console.log(this);
	}
}


person.eat(); // person. this一开始是指向window的,在此处person调用eat时隐式的转换成person
person.drink(); // window. (对象先挂在全局,然后赋值给person,所以它的外层this是指向window)

新知:闭包
JavaScript笔记——ES6新增语法篇_第19张图片

  1. 箭头函数不能作为构造函数来使用
  2. 在箭头函数中不存在arguments对象,所以使用 …(rest/spread)来代替
  3. yield 命令不能生效,在generator 函数中

箭头函数的使用场景

1: (这个需要先去回顾一下)
传统写法:

(function(){
     
	// 构造函数
	function Button(){
     
		this.button = document.getElementById("button");
	}
	Button.prototype = {
     
		init(){
     
			this.bindEvent();
		},
		bindEvent(){
     
			this.button.addEventListener('cilck',this.clickBtn.bind(this),false);

		},
		clickBtn(){
     
			console.log(this);
		}
	}

	new Button().init();
})();

使用箭头函数的写法:

(function(){
     
	function Button(){
     
		this.button = document.getElementById("button");
	}
	Button.prototype = {
     
		init(){
     
			this.bindEvent();
		},
		bindEvent(){
     
			this.button.addEventListener('cilck',(e) => this.clickBtn(e),false);

		},
		clickBtn(e){
     
			console.log(e);
			console.log(this);
		}
	}

	new Button().init();
})();

2.

在这里插入代码片
  1. 简单的函数表达式,得出唯一的return 计算值,并且函数内部没有this引用
    递归、事件绑定、解绑定,用重构箭头函数的方式
  2. 内层函数表达式,需要调用this,确保this使用正确。通常会这么干:var self = this 或 bind(this); 这时候就可以使用箭头函数

JavaScript笔记——ES6新增语法篇_第20张图片
4. 在这里插入图片描述

你可能感兴趣的:(JavaScript)