JavaScript笔记——ES6新增语法篇

ES6过渡史

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

在这里插入图片描述
在这里插入图片描述
2. traceur

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

  1. kiss原则:keep it simple,stupid

1. 块级作用域

在这里插入图片描述

2. let 关键字

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

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

在这里插入图片描述

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]();
}

区分:
在这里插入图片描述

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

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

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声明的

在这里插入图片描述
在这里插入图片描述
惰性求值: 函数的参数为表达式的情况下,参数加载的方式是惰性求值的方式,每(执行)一次都要重新计算表达式的值

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 对象解构

在这里插入图片描述
对象的属性还能拼接:

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

console.log(person);

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

在这里插入图片描述
▲:对象解构还需要捂一捂

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


()用法

在这里插入图片描述
解决:加一个括号,让大括号不再是作用域,而是表达式(如下)

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

  • 用 let / var 声明,加括号就报错
    (所以,定义参数的方式中间不能加括号)
    在这里插入图片描述

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

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); // {}

在这里插入图片描述
模式匹配:
首先要模式一样才能进行匹配
其次,有括号的时候一定要注意 这括号起的是什么作用

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

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

在这里插入图片描述
在这里插入图片描述

函数参数解构


计算属性解构:

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

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); // 报错

这也是为什么调用函数时不传内容会报错,是因为空的内容并不能进行隐式转换
在这里插入图片描述


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. 隐式绑定:谁调用,指向谁

在这里插入图片描述

3. 显示绑定:call、apply、bind
4. new (优先级最高)

箭头函数(表达式)

格式:

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

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

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

箭头函数可以和解构赋值结合来用
在这里插入图片描述
在箭头函数中不存在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运算符——收集

在这里插入图片描述
在这里插入图片描述(反问 = 返回)


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

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)

新知:闭包
在这里插入图片描述

  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); 这时候就可以使用箭头函数

在这里插入图片描述
4. 在这里插入图片描述

标题“51单片机通过MPU6050-DMP获取姿态角例程”解析 “51单片机通过MPU6050-DMP获取姿态角例程”是一个基于51系列单片机(一种常见的8位微控制器)的程序示例,用于读取MPU6050传感器的数据,并通过其内置的数字运动处理器(DMP)计算设备的姿态角(如倾斜角度、旋转角度等)。MPU6050是一款集成三轴加速度计和三轴陀螺仪的六自由度传感器,广泛应用于运动控制和姿态检测领域。该例程利用MPU6050的DMP功能,由DMP处理复杂的运动学算法,例如姿态融合,将加速度计和陀螺仪的数据进行整合,从而提供稳定且实时的姿态估计,减轻主控MCU的计算负担。最终,姿态角数据通过LCD1602显示屏以字符形式可视化展示,为用户提供直观的反馈。 从标签“51单片机 6050”可知,该项目主要涉及51单片机和MPU6050传感器这两个关键硬件组件。51单片机基于8051内核,因编程简单、成本低而被广泛应用;MPU6050作为惯性测量单元(IMU),可测量设备的线性和角速度。文件名“51-DMP-NET”可能表示这是一个与51单片机及DMP相关的网络资源或代码库,其中可能包含C语言等适合51单片机的编程语言的源代码、配置文件、用户手册、示例程序,以及可能的调试工具或IDE项目文件。 实现该项目需以下步骤:首先是硬件连接,将51单片机与MPU6050通过I2C接口正确连接,同时将LCD1602连接到51单片机的串行数据线和控制线上;接着是初始化设置,配置51单片机的I/O端口,初始化I2C通信协议,设置MPU6050的工作模式和数据输出速率;然后是DMP配置,启用MPU6050的DMP功能,加载预编译的DMP固件,并设置DMP输出数据的中断;之后是数据读取,通过中断服务程序从DMP接收姿态角数据,数据通常以四元数或欧拉角形式呈现;再接着是数据显示,将姿态角数据转换为可读的度数格
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值