ES6基础
2020-04-29 15:54:45 12 举报
AI智能生成
个人前端学习
作者其他创作
大纲/内容
let
变量声明
1.使用var或者直接使用的变量名定义声明的变量(污染全局对象)<br><br>变量声明后,即挂在了全局对象window上,作为其属性和方法,通常也可以省略window对象直接调用;当我们访问不存在的变量时,即会自动创建一个变量,详见本章笔记附录:<br><br>
2、var与let的主要区别:<br><br>— —let声明变量 只在当前块级作用域有效(即{}),不会污染全局对象window;<br><br>— —let或者const声明变量,不能被重复声明;<br><br>— —let不存在变量提升(使用变量前,必须先声明;如果是使用var,会有一个预解析的状态,使变量被赋值为undefined,且使所有的var 和function声明的变量和函数提至最前面)<br><br>变量提升:在变量声明前,调用变量,会将变量提升到调用语句前,仍会读到该变量。
const
声明常量
const 声明常量<br><br>1.常量必须在声明的时候赋值,否则报错<br><br>2.常量不能被修改, 但是!!为引用类型的时候,可被修改,const只能保证指向的引用地址不变,但是地址中的内容是可以改变的,比如xiaoming.age = 22
与let类似的特性:<br><br>不能重复声明;<br><br>不存在提升;<br><br>只在当前(快级)作用域内有效<br><br>常量为引用类型的时候不能保证不可变
const 声明常量时,只能保证常量所指向的地址不变(eg:18、23同地址,25与18、23不同地址),但不能保证地址上的值(23改变的只是18内的值)不去发生改变。类似的还有数组,改变其中的值谋问忒,但改变地址(eg:被赋予新数组)就有问题。
常量内引用Object.freeze()可保证引用类型不被修改;
const扩展
1.Object.defineProperty(对象名,属性名,{value:属性值 }):可添加、修改属性值,也可扩展属性;<br><br>对象名:必须,被添加或者修改属性的对象。<br><br>属性名:必须,被修改的属性名称<br><br>{value:属性值 }:必须,属性描述符,它可以针对数据属性或访问器属性<br><br>返回值:已修改的对象。<br><br>用法:向对象添加新属性。修改现有的属性特征 <br>
通过wirteable:false则可以只读不能修改;<br><br>通过wirteable:true之才可以修改新属性值。<br><br>例:Object.defineProperty(obj,i,{<br><br><br><br>writable:false---<br><br><br><br>});
2.Object.seal(对象名):让一个对象密封,密封对象不能添加新的属性,不能删除已有的属性,以及不能修改已有属性的可枚举性、可配置性,可写性,但是可以修改已有属性对象的值。<br><br>返回值:被密封后的对线
3.Object.hasOwnProperty(属性名):检测是否是自己定义的属性,<br><br><br><br>属性名:必须<br><br><br><br>返回值:是则返回true,不是则返回false<br>
ES6扩展
自执行函数原理阐释
(一)基本语法格式<br><br>( function (formal arguments){ } ) (actual arguments)
(二)为什么会是这么写的?<br><br>1.顾名思义:自执行函数,也就是会随着脚本的加载,会自动执行的函数。<br><br>2.函数的使用:我们知道函数要执行,就必须要进行调用,函数的调用方式分为两种,一种是使用functionName(),加以调用;另一种是使用functionVariateName(),即变量名()加以调用。<br><br>3.万不离其宗:函数的自执行,也必须按照基本语法来才能调用。<br><br>4.对比分析:将自执行函数的基本写法与函数的调用语法对比一下<br><br>— —常规调用 :functionName() || functionVariateName()<br><br>— —自执行函数:(function(){})()<br><br>5.明显的结论:形式上的等价于<br><br>(function(){})==functionName==functionVariateName<br><br>6.实际的使用形式:<br><br>— —(function(formal arguments){})(actual arguments)<br><br>— —(functionName)(arguments)<br><br>— —(functionVariateName)(arguments)
三)我们为什么需要使用自执行函数?<br><br>充分发挥自执行函数提供的密闭空间作用域的优势<br><br>— —避免污染变量内存,即全局变量window(浏览器端);<br><br>— —构建密闭作用域(如老师的代码)
作用域
//ES6之前版本<br><br>1.全局作用域(window);<br><br>2.函数作用域<br><br>3.eval作用域(即是指:eval函数的() 包含的部分)<br><br>
//ES6<br><br>4.块级作用域(即使用 {...} 包含的代码区域)<br><br>— —if(){...};<br><br>— —switch(){...};<br><br>— —for(){...};<br><br>包含了两级作用域,()内是一个作用域,{}是其子作用域<br><br>— —try(){...}catch(err){...};<br><br>— —{...}<br><br>tips:支持嵌套块级作用域;除对象的{}外;<br><br>5.暂存死区:<br><br>只要在块级作用域中,使用let或const关键字声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
解构赋值
数组的结构赋值
一、简单的解构赋值:<br><br>const arr = [1,2,3,4];<br><br>let [a,b,c,d]= arr;<br><br>我的理解就是,数组的解构赋值是提供已知数据的数组a,赋值给相同结构、内容为变量的数组b,这样一次性的把b都给赋值了。
二、更复杂的匹配规则:<br><br>const arr = ['a','b',['c','d',['e','f','g']]];<br><br>const [ , ,[ , ,[ , ,g]]]=arr;<br><br>这样的话,就是变量g只取数组arr中的'g',但是变量g所在的数组的结构要和数组arr匹配,逗号不能少;
三、扩展运算符:<br><br>const arr1 = [1,2,3];<br><br>const arr2 = ['a','b'];<br><br>const arr3 = ['zz',1];<br><br>const arr4 = [...arr1, ...arr2, ...arr3];<br><br>如果arr4中不加... ,那么数组arr4中显示的就是[Arr1,Arr2,Arr3],如果加上... ,那么arr4中显示的就是一个数组,这个数组是前三个数组的集合[1, 2, 3, "a", "b", "zz", 1]。
结合扩展运算符和结构赋值<br><br>const arr = [1,2,3,4,5,6];<br><br>const [a,b,...c] = arr;<br><br>这样,c的结果就是[3, 4, 5, 6],c就是取除了a,b后面所有的值;但是扩展运算符和数组的结构赋值结合的话,数组变量中,扩展运算符只可以放在最后,后面 不可以有变量([a,b,...c,d]这样就是错的)。
四、默认值<br><br>数组的解构赋值,变量的默认值是undefined<br><br>const arr = [1,undefined,undefined];<br><br>const [a,b,c,d] = arr;<br><br>b、c被赋值给了undefined,d的话,在arr中没有被匹配到,取的是默认值,是undefined;因为const常量被声明的时候必须被赋值,这样写没有报错,说明直接给了默认值;
如果匹配的的数组值是undefined,被匹配的数组,常量中若有给值的话,那么就取用给的值,b为2,c为undefined,d为aaa,也即只有数组是undefined的时候,才可以匹配被给的数值;<br><br>但如果arr中给的是null,那么即使被匹配常量中有值的话,也不会取值<br><br>(比如const arr=[1,null,undefined] ;<br><br>const [a,b=2,c,d='aaa'] = arr;这样b还是不等于2,b被取值为null)。
五、交换变量<br><br>ES6之前,交换变量的方法是给创建一个新的变量,然后进行交换;<br><br>利用解构赋值交换会很方便:<br><br>let a = 20;<br><br>let b = 10;<br><br>[a,b] = [b,a];
六、接收多个 函数返回值<br><br>function getUserInfo(id){<br><br>return [<br><br>true,<br><br>{<br><br>name:'小明',<br><br>gender:'女',<br><br>id:'id'<br><br>},<br><br>'请求成功'<br><br>];<br><br>};<br><br>const [status,data,msg] = getUserInfo(123);<br><br>因为这样函数执行后返回的是一个数组(数组中是一个布尔值,一个对象,一个字符串),这样就可以用到解构赋值了,赋值给三个常量;<br><br>之前的做法是将函数的执行赋值给一个变量a(或者常量),然后通过变量a[i]赋值给各个变量b(或常量),打印变量b的时候就可以看到各个函数的返回值。
对象的解构赋值
1.数组与对象区别<br><br>数组有序,根据下标取值;<br><br>对象是无序的,结构赋值时,变量名和对象的属性名相同,就可以匹配,取到对象中属性的属性值; <br>
2.无需保留前项位置,即使用逗号;
3.赋值对象匹配---如图<br>当对象为中其中一个属性为数组时,则需按照数组方式来解析结构,另当前者为数组的同时,里面的数组项为对象时,获取相同的属性名,则不能写相同的属性名(const 申明的变量名不能重名)---------用:隔开,只可前者属性名相同,同时将属性值赋予;后者则是需要属性名:属性值(变量名称),是将其属性名的属性值赋予变量<br>*****对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量,
要拿某个属性只要构造相同的数据结构就行,属性重名时可以在属性后加个:,形成A:B,表示拿A的属性但是复制给B
4.扩展运算符...<br><br>1)可通过扩展运算符,匹配后面所有的属性<br><br>const obj = {<br><br>saber:'阿尔托利亚',<br><br>archer:'卫宫',<br><br>lancer:'瑟坦达'<br><br>};<br><br>const{saber,...oth }= obj;----表示将将剩下的两项以oth为名的对象;<br><br>同样扩展运算符不能在中间,只能在末尾<br><br><br>
2)...扩展运算符也可使用,独享合并<br><br>const obj1 = {<br><br>archer:'卫宫',<br><br>lancer:'瑟坦达'<br><br>}<br><br>const obj = {<br><br>saber:'阿尔托利亚',<br><br>...obj1<br><br>};-----将obj1的属性合病到obj
5.默认值<br><br>与数组相似,当匹配到undefind,就会取默认值;<br><br>let girlfriend = {<br><br>name:'小红',<br><br>age:undefind,<br><br>};<br><br>let {name ,age = 24, hobby = ['学习'] } = girlfriend;----age则为默认值24岁,当不是时,则匹配到属性值;
字符串的解构赋值
1.通过数组形式来匹配字符串;
2.扩展运算符...<br><br>...oth 是将剩下的字符串的字母以数组的形式全部拆分为25个字母,而非单词;
3.图中的三种方式都是如第2点所诉,以数组的形式全部拆分为单独字母,而非单词;
1.关于oth,把剩下的以数组的形式赋值给oth<br><br>2.切割字符串的三种方式<br><br>const [...spStr1] = str;<br><br>const spStr2 = str.spilt('');<br><br>const spStr3 = [...str];<br><br>3.提取属性<br><br>const {length}=str
数值与布尔值的解构赋值
1.当str(字符串).length时,是将字符串临时包装成对象获取,获取完后,又重新返回str;
函数参数的解构赋值
0 条评论
下一页