网页开发基础--ES6

目录

ES6基础入门之let、const

变量声明

let和var的主要区别

ES6之前的作用域

块级作用域

let面试常见例子

const

const与let类似的特性

常量不可变

怎么解决引用类型的常量可以被修改的问题?

ES6之前怎么声明常量?

ES6变量的解构赋值

数组的解构赋值

数组的解构赋值

更复杂的匹配规则

扩展运算符 ...

默认值

交换变量

接收多个函数返回值

对象的解构赋值

对象解构赋值的用法

稍微复杂的解构条件

扩展运算符 ...

如何对已经申明了的变量进行对象的解构赋值

默认值

对象的解构赋值的主要用途

字符串的解构赋值

数值与布尔值的解构赋值

函数参数的解构赋值


ES6基础入门之let、const

变量声明

var声明

var name='hiyori'

直接使用

window.location.href===location.href

说明:这种不加var声明的定义方式,相当于在全局对象window上挂了一个属性,会造成全局对象污染 ,不建议这么做

let和var的主要区别

  • let声明的变量只在当前(块级)作用域内有效
  • let声明的变量不能被重复声明
  • let不存在变量提升

ES6之前的作用域

全局作用域、函数作用域、eval作用域

块级作用域

  • 通俗的讲,就是一堆花括号中的区域{...}
  • 块级作用域可以嵌套
/* let声明的变量只在当前(块级)作用域内有效 */
//example1
{
  var a = 1;
  let b = 2;
}
console.log(a);    //打印a
console.log(b);    //出了块级作用域,报错信息为未定义
 
//example2
{
  let a = 1;
  {
    console.log(a);    //这里属于a的作用范围,打印1
    let b = 2;
  }
  console.log(b);    //这里不属于b的作用范围,报错
} 
 
//example3
for (let i = 0; i < 3; i++) {
 
};
console.log(i);    //报错
 
for (var i = 0; i < 3; i++) {
  console.log(i);
};
console.log(i);    //打印3,var定义的i并不会被释放,因为初始化时定义的i相当于是在循环语句的作用域之外定义的
/* 使用let或者const声明的变量不能被重新声明 */
var dad = '我是爸爸!';
var dad;
console.log(dad);    //重新声明,没有被赋值,该变量还是'我是爸爸'
var dad = '我才是爸爸!';
console.log(dad);    //修改为新的值
 
let son = '我是儿子';
let son;    //报错,提示son已被声明过
let son = '我才是儿子';    //报错,提示son已被声明过
/* let不存在变量提升 */
console.log(dad);    //undefined
var dad='我是爸爸';
//以上情形就是因为变量提升
//预解析时会先解析带有var关键字的变量,并赋值为undefined,执行代码时才赋真正的值
//相当于
var dad;    //变量声明被拉到最前面,而后赋值
console.log(dad);
dad='我是爸爸';
 
console.log(dad);    //报错,提示未定义该变量
let dad='我是爸爸';
//用let定义的变量不会把声明拉到最前面,因此不具有变量提升
//暂存死区
var monkey = '我是美猴王';
{
  console.log(monkey);    //我是..
  var monkey = '我觉得我还能再抢救一下!';
}
console.log(monkey);    //我觉得..
 
let monkey = '我是美猴王';
{
  console.log(monkey);    //报错
  let monkey = '我觉得我还能再抢救一下!';
}
console.log(monkey);

let面试常见例子

q: 生成十个按钮 每个按点击的时候弹出1 - 10
var i = 0;
for (i = 1; i <= 10; i ++) {
  (function(i) {
    var btn = document.createElement('button');
    btn.innerText = i;
    btn.onclick = function() {
      alert(i)
    };
    document.body.appendChild(btn);
  })(i);
}
    //在外面加上自执行匿名函数,就会形成独立的函数作用域,i作为参数传进来,在作用域中获得的就是实时更新的i
    //如果没有定义一个自执行的function,那么这里每次点击弹出的都是11
    //因为发生点击事件后要去寻找i,本层找不到就会到上一层去找,上一层的i在循环结束后值为11
    //因此事件中获取到的i的值也是11
 
 
//使用let定义,可以实现和添加自执行函数一样的效果
for (let i = 1; i <= 10; i ++) {
  var btn = document.createElement('button');
  btn.innerText = i;
  btn.onclick = function() {
    alert(i)    
  };
  document.body.appendChild(btn);
}

const

常量——不可改变的量

和声明变量一样,基本只是关键字的区别

常量必须在声明的时候赋值,否则报错:Missing initiaizer in const declaration

const a;    //不赋值,会报错
var b=2;
let c;

const与let类似的特性

不能重复声明

不存在变量提升

只在当前(块级)作用域内有效

常量不可变

一旦声明常量,就不能再改变

但常量为引用类型的时候,不能保证不可变

const NAME='xh';
NAME='xm';    //报错,提示常量不能被修改

说明:const只能保证引用常量的地址不变,不能保证它里面的值不变。

//对象
const xiaoming={
    age:14;
    name:'xm';
}
xiaoming.age=22;    //允许修改
xiaoming={};    //报错,不允许被修改,因为相当于把一个新的地址给了xiaoming这个常引用对象
 
//数组
const ARR=[];
ARR.push(1);    //允许添加
ARR=[];    //报错,不允许被修改,还是相当于把一个新的地址给了ARR这个常引用数组

怎么解决引用类型的常量可以被修改的问题?

Object.freeze()

const xiaoming = {
  age: 14,
  name: '小明'
};
Object.freeze(xiaoming);    //xiaoming对象中的值也不允许被修改了
console.log(xiaoming);
xiaoming.age = 22;    //不报错,但不会发生改变
xiaoming.dd = 11;    //不报错,但不会发生改变
console.log(xiaoming);
 
const ARR = [];
Object.freeze(ARR);    //ARR数组中的值也不允许被修改了
ARR.push(1);    //报错,提示不能被扩展
console.log(ARR);

ES6之前怎么声明常量?

用var声明,假装是常量

var BASE_COLOR = '#ff0000';

Object.defineProperty();

var CST = {a: 1};
Object.defineProperty(CST, 'a', {
  writable: false
});
//writable:只读,不能被修改
Object.seal(CST);    //只能防止被扩展
//Object.seal+writable:false才能达到freeze()的效果

自行封装一个freeze()

// 1. 遍历属性和方法
// 2. 修改遍历到的属性的描述
// 3. Object.seal()
 
Object.defineProperty(Object, 'freezePolyfill', {
  value: function(obj) {
    var i;
    for (i in obj) {
      if (obj.hasOwnProperty(i)) {
        Object.defineProperty(obj, i, {
          writable: false    //每个属性都不能被修改
        });
      }
    }
    Object.seal(obj);    //整个对象不能被扩展
  }
});
 
const xiaoming = {
  age: 14,
  name: '小明',
  obj: {
    a: 1
  }
};
 
Object.freezePolyfill(xiaoming);

ES6变量的解构赋值

解构赋值语法是一个JavaScript表达式,这使得可以将值从数组或属性从对象提取到不同的变量中

数组的解构赋值

数组的解构赋值

// 数组的解构赋值
 
const arr = [1, 2, 3, 4];
let [a, b, c, d] = arr;
 
//会根据元素在数组中所在的位置一一对应匹配,a=1,b=2……

更复杂的匹配规则

// 更复杂的匹配规则
 
const arr = ['a', 'b', ['c', 'd', ['e', 'f', 'g']]];
 
const [ , b] = arr;    //只返回b
const [ , , g] = ['e', 'f', 'g']    //只返回g
const [ , , [ , , g]] = ['c', 'd', ['e', 'f', 'g']];    //只返回g
const [ , , [ , , [ , , g]]] = arr;    //只返回g

扩展运算符 ...

// 扩展运算符  ...
 
const arr1 = [1, 2, 3];
const arr2 = ['a', 'b'];
const arr3 = ['zz', 1];
const arr4 = [...arr1, ...arr2, ...arr3];    //可以把arr1、arr2、arr3合并起来
 
const arr = [1, 2, 3, 4, 5, 6];
const [a, b, ...c] = arr;    //会把3,4,5,6作为一个数组赋给c
 
const [a, b, ...c,d] = arr;    //错误

注意:带扩展运算符的变量后面不能再有其他变量,因为扩展运算符就是用来取最后几个元素进行合并的

默认值

// 默认值
 
const arr = [1, null, undefined];
const [a, b = 2, c, d = 'aaa'] = arr;    //设置默认值,当匹配到undefined时,就使用默认值
 
//a=1,b=null,c=undefined,d='aaa'

说明:解构赋值时没有匹配到的就被赋值为undefined 

交换变量

// 交换变量
 
let a = 20;
let b = 10;
 
//方法①
let temp;
temp = a;
a = b;
b = temp;
 
//方法②,利用解构赋值
[a, b] = [b, a];

接收多个  函数返回值

// 接收多个 函数返回值
 
function getUserInfo(id) {
  // .. ajax
 
  return [
    true,
    {
      name: '小明',
      gender: '女',
      id: id
    },
    '请求成功'
  ];
};
 
const [status, data, msg] = getUserInfo(123);
 
//status匹配到函数返回值第一项布尔值,data匹配到函数返回值第二项对象,msg匹配到函数返回值第三项文字

对象的解构赋值

对象的解构赋值与数组的解构赋值相似

等号左右两边都为对象结构

const {a,b}={a:1,b:2};

左边的{}中为需要赋值的变量

右边为需要解构的对象

对象解构赋值的用法

// 对象的解构赋值
 
const obj = {
	saber: '阿尔托利亚',
	archer: '卫宫'
};
const { saber, archer1 } = obj;    //archer属性名不匹配,archer1的值是undefined

注意:对象的解构赋值要求不同对象的属性名要一致,才能匹配。因为数组是有序的,而对象是无序的,必须用属性名去匹配,而不是用位置去匹配。

稍微复杂的解构条件

// 稍微复杂的解构条件
 
const player = {
	nickname: '感情的戏∫我没演技∆',
	master: '东海龙王',
	skill: [{
		skillName: '龙吟',
		mp: '100',
		time: 6000
	},{
		skillName: '龙卷雨击',
		mp: '400',
		time: 3000
	},{
		skillName: '龙腾',
		mp: '900',
		time: 60000
	}]
};
 
const { nickname } = player;    //返回感情的戏∫我没演技∆
const { master } = player;    //返回东海龙王
const { skill: [ skill1, { skillName }, { skillName: sklName } ] } = player;    
//保持格式一致,就可以解构skill里的属性
//对数组进行赋值时变量名可以随便起,skill1获得skill数组的第一项,skillName获得数组第二项中的skillName龙卷雨击
//这时如果想要获得skill数组第三项的skillName再次使用{skillName}是不行的,因为const声明的变量中已经有skillName了
//我们需要另外起一个名字,只要在属性名后面加上:新名字,就可以解决这个问题,意思是把skillName中的值赋给sklName
 
const { skill } = player;    //返回一个数组
const [ skill1 ] = skill;    //skill是一个数组,skill1是数组元素的第一项——龙吟,100,6000
const { skill:[skill1] }=player;    //与上一行完全一样,但不会取到skill

扩展运算符 ...

// 结合扩展运算符
 
const obj = {
	saber: '阿尔托利亚',
	archer: '卫宫',
	lancer: '瑟坦达'
};
 
const { saber, ...oth } = obj;    //会把除了saber以外的剩下所有项赋值给oth
const obj1 = {
	archer: '卫宫',
	lancer: '瑟坦达'
}
 
const obj = {
	saber: '阿尔托利亚',
	...obj1,    //会把obj1所有属性合并成一个对象
};

如何对已经申明了的变量进行对象的解构赋值

// 如何对已经申明了的变量进行对象的解构赋值
 
let age;
const obj = {
	name: '小明',
	age: 22
};
 
({ age } = obj);
//{age}外面如果不加(),会被编译器理解成块级作用域,然后报错。
 
//最好的方法是带上变量声明
const obj = {
	name: '小明',
	age: 22
};
let {age}=obj;

默认值

// 默认值
 
let girlfriend = {
	name: '小红',
	age: undefined,
};
 
let { name, age = 24, hobby = ['学习'] } = girlfriend;
//name='小红',age=24

对象的解构赋值的主要用途

提取对象属性

// 提取对象属性
 
const { name, hobby: [ hobby1 ], hobby } = {    //把hobby值赋给hobby1,再定义一个hobby就获取到对象的hobby属性值
	name: '小红',
	hobby: ['学习']
};

使用对象传入乱序的函数参数

function AJAX({    //传参时解构赋值,可以不按顺序赋值,如果type没有设置默认为get
	url,
	data,
	type = 'get'
}) {
	// var type = option.type || 'get';
	// console.log(option);
	console.log(type);
};
AJAX({
	data: {a: 1},
	url: '/getinfo',
});

获取多个函数返回值

// 获取多个 函数返回值
 
function getUserInfo(uid) {
	// ...ajax
	return {
		status: true,
		data: { name: '小红' },
		msg: '请求成功'
	};
};
const { status, data, msg: message } = getUserInfo(123);

字符串的解构赋值

// 字符串的结构赋值
const str = 'I am the bone of my sword'; // 我是剑骨头
 
const [ a, b ,c, ...oth ] = str;    
//a=I,b= ,c=a,oth=m the bone of my sword,注意这里oth是一个数组,每个字符是一个数组元素
 
const [ ...spStr1 ] = str;    //spStr1是一个数组,每个数组元素是str的一个字符
const spStr2 = str.split('');    //同上一句效果一样
const spStr3 = [ ...str ];    //同上一句效果一样
 
// 提取属性
 
const { length, split } = str;

数值与布尔值的解构赋值

// 数值与布尔值的解构赋值
 
const { valueOf: vo } = 1;
const { toString: ts } = false;

函数参数的解构赋值

// 函数参数的解构赋值
 
function swap([x, y]) {
	return [y, x];
};
 
let arr = [1, 2];
arr = swap(arr);
 
//定义一个Computer的构造函数
function Computer({
	cpu,
	memory,
	software = ['ie6'],
	OS = 'windows 3.5'
}) {
 
	console.log(cpu);
	console.log(memory);
	console.log(software);
	console.log(OS);
 
};
 
//声明一个Computer对象
new Computer({
	memory: '128G',
	cpu: '80286',
	OS: 'windows 10'
});

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章