- let
- let 定义变量没有变量的提升(没有预解释)
- let 定义的变量不能重复定义(无论函数还是let定义的变量都不可以重复定义)
- 虽然不进行预解释,但是代码执行前,也是将定义的变量提前过滤一遍,一旦发现不合法的就直接报错了,代码也不会执行了。
- { }
- 是一个私有作用域 ,块级作用域
- // 自执行函数 { let a = 100; console.log(a); }
- 注意:eval将字符串转为对象的时候,一定要加一个()
let test = "{ name: 'Tom', age: '28' }";
let obj = eval('('+ test +')');
console.log('obj:',obj);
3. const
- 定义的是静态变量(常量),不能修改值,必须要赋值(不赋值会报错)
- const不能重复声明(不管变量a是let动态变量,还是const静态变量,都不可以重复定义)----前提:同一作用域下
4. 数组赋值
- 解构赋值
let [a,b,c] = [1,2,3];
console.log(a,b,c); //1,2,3
let ary = ["a", "b"];
let [a,b,c] = ary;
console.log(a,b,c); //a,b,undefined
let ary = ["a", "b", "c", "d"];
let [a,b,c] = ary;
console.log(a,b,c); //a,b,c
- 嵌套赋值
let [x,y,[s],[[f]]] = [1,2,[3],[[4]]]; // s、f均为变量,非数组console.log(x,y,s,f);
- 省略赋值
let array= [1,2,3,4,5];let a = array[0];let b = array[array.length - 1];//x是array的第一项,y是array的第五项let [x,,,,y]=array;console.log(x,y);
- 不定参数赋值
let [a,...b] = [1,2,3,4,5];console.log(a,b); // 1, [2,3,4,5]let [,,x,,...y] = [1,2,3,4,5,6,7,8,9,0];console.log(x,y);
- 默认值
// 1、变量名==属性名let {n1, n2} = obj;console.log(n1,n2);// 2、变量名不等于属性名let {n1: x1, n2: x2} = {n1: 'n1', n2: 'n2'};let {n, m:m1} = {n: 'nn', m: 'mm'};console.log(n,m1); //let [f0,f1]= [1];console.log(f0,f1);let [f2,f3=2] = [1];console.log(f2,f3);//判断一个位置是否有值,严格===判断,如果数组中成员不严格等于undefined,默认值不会生效。let [f=1] = [null];console.log(f);function fn(){console.log("哈哈哈");}let [x=fn(),y=0] = [1];console.log(x,y);//只要变量(比如x)所占在数组中的位置的值不是undefined,fn()根本不会触发执行
- 对象赋值
- 解构赋值
let {x,y="Y"}={x:"X",y:"YY"};let {m:[m1],n}={m:[1],n:1};//赋的值不是一个对象,是个其他数据类型的值,会默认将其他数据类型转为对象,再进行解构赋值let {x,y,__proto__}=1; //{__proto__:Number}console.log(x,y); //undefined,undefinedconsole.log(__proto__);console.log(Object(1)); //{__proto__:Number}let {b,constructor}=Boolean.prototype;console.log(Object(Boolean.prototype));console.log(constructor);//没有默认值的形参的长度let {length,name} = function (a,b=1) { };console.log(Object(function (a, b) { }));console.log(length,name);//null和undefined 不能转为对象 会报错//let {nn}=null;let {mm}=undefined;console.log(nn);console.log(mm);
- 对象数组的嵌套
let obj = {a1:[1,2,3], a2:"123"};//x=obj.a1[0]、y=obj.a1[1]let {a2, a1:[x,y]} = obj;console.log(a2, x, y);let obj1 = {s:{n:'1'}, n:[1,'2',3,'4'], m:[[1]]};let {m:[x1], s:{n}, n:[,...m2]} = obj1;console.log(x1,n,m2); //[1], '1', ['2',3,'4']
- 默认值
let obj = {y: 2};console.log(obj.x); //undefinedlet {x=1,y} = {y: 2};console.log(x,y);let {m:n} = {}; //m: undefinedconsole.log(n); //n: undefinedlet {m:n=4} = {}; //m: undefinedconsole.log(n); //n: 4let {a:cc=22} = {a: 12};console.log(cc); //12//默认值生效的条件是对象的属性必须是undefinedlet {v=3} = {v: undefined};console.log(v); // v:3let {v=3}={v:null};console.log(v); //nulllet {f:{b}} = {b: 'bb'};//f: undefined//{b}=undefinedconsole.log(b); //Cannot destructure property `b` of 'undefined' or 'null'//如果解构模式中嵌套的是对象,而且子对象所在的父属性不存在,就会报错
- 其他问题
- 赋的值不是一个对象,是个其他数据类型的值,会默认将其他数据类型转为对象;
- 为了避免错误,不要将{}写在行首,JavaScript引擎会将{a}理解为一个代码块;
- null和undefined 不能转为对象 会报错
- 比如:eval("{s: 'ss',d: 'd'}");
- ({a}={a: 'a'}); console.log(a); //a
6. 字符串
- 解构赋值
//此时是将字符串转为类似数组的一个对象let [x,y,z] = '123';console.log(x,y,z);let {length} = '12345';console.log(length);
- 方法
- includes(); //判断字符串中有没有指定字符,有的话返回true,没有返回false、第二个参数~~开始查找的索引,默认是0;
- startsWidth(); //是不是以某个字符作为开头,第二个参数:开始查找的索引,默认是0;true/false
- endsWidth(); //是不是以某个字符作为结尾,第二个参数:开始查找的索引,默认是0;true/false
let str = 'asdfghjkl';console.log(str.includes('a',2));console.log(str.startsWith('a',2));console.log(str.endsWith('l'));
- repeat(n); //将 字符串重复n次返回,原字符串不变
console.log(str.repeat(2),str);//小数,向下取整console.log(str.repeat(2.6));//负数、Infinity 报错console.log(str.repeat(-2));console.log(str.repeat(Infinity));//0~-1, 先向下取整运算结果为0console.log(str.repeat(-0.3)); // ''//NaN --> 0console.log(str.repeat(NaN)); // ''//字符串, 将字符串转为数字console.log(str.repeat('2')); // 'asdfghjklasdfghjkl'console.log(str.repeat('sdfsdf')); // ''
- 模板字符串(字符串)
let str = 'I love U';document.body.innerHTML = '<h1>'+ str +'</h1>';//模板字符串let str1 = `<h1>${str}</h1>`; //拼接字符串document.body.innerHTML += str1;//es6 保留换行和空格console.log('hahahahah hahahah'); //平时 换行 consolelet s1 = `hhhhathe weather isfine.`;console.log(s1); //es6保留换行 console//`特殊符号需转义(\`)console.log(`sss\`1234`);//{可以实现运算}let x=1;let y=2;console.log(`${x}+${y}=${x+y}`);//调用函数function fn(x){return x;}let s2 = 'sss';console.log(`函数fn输出的结果是${fn(s2)}`);let s3 = 'return' + '`hello ${wd}`';let fun = new Function('wd',s3);fun('ZFPX');
7. 数组的扩展
- Array.from(), Array.of()
// Array() ----即是一个类,也是一个方法,将传进来的值变成数组返回;【注意】只传一个参数n,代表返回数组的长度(4个空位)(eg: Array(1,2,3,4)、Array(4))//1、Array.of ----跟Array()一样,只有一点区别:就是传一个参数时候返回就是当前参数组成的数组(eg: Array.of(1,2,3,4)、Array.of(4))//2、Array.from() ----参数是:数组或者类数组;返回值是一个新的数组。将类数组对象( 所谓类数组对象,最基本的要求就是具有length属性的对象)变成数组
- 数组实例的copyWithin()
copyWithin(target,start,end);//target: 必填,从该位置开始替换数据//start: 选填,默认值0,从该位置开始读取数据//end: 选填,默认值是数组的长度,到该位置前停止读取数据
- 数组实例的find() 和 findIndex()
//1、find ----先遍历数组,一项一项的执行,一旦函数返回值是true,停止查找,返回当前项,一直到最后一项还没有返回true,最终结果就是undefined。let arr = [1,2,3,4,5,6];arr.find(function (item, index, input){//item:当前项, index:索引, input: 原数组return item==4;});//2、findIndex ----返回值是当前项的索引,一直到最后都没有返回true的最终结果就是undefined
- 数组实例的fill()
fill(value,start,end) ----填充数组的//value: 必填的,填充的值//start: 开始填充的位置,默认值0,可选的//end: 停止填空的位置,可选的,不包括eg: //得到有7个1的数组Array(7).fill(1);
- 数组实例的entries() 和 keys()
//1、keys() ----数组索引值eg: let arr = [1,2,3,4,5];for(var key in arr){
console.log("索引"+key);};for(let item of arr){console.log("当前项"+item);}//keys() 遍历索引for(let key of arr.keys()){console.log(key);}//2、entries() ----索引+对应项的值for(let [index,item] of arr.entries()){console.log(index,item);}
- 数组实例的includes()
includes() ----判断数组中有没有某一项,返回值是true/false
- 数组的空位
//1、ES5中方法对空位处理都不太一致,大部分都是跳过空位[1,,,2,,].forEach(function(item){console.log(item);});//2、ES6不跳过空位,会将空位处理为undefined[1,,,2,,].map(function(item){return item;});
- 函数的扩展时
- 函数参数问题
- 一般把函数形参变量的默认值放后面
- function fn(x,y,z=1){ }; fn(1,2);
- 参数集合
- function fn5(){ console.log(arguments.length); }; fn5(1,2,3,4,5); // arguments.length~~实参的长度
- function fn6(x,y,z){}; console.log(fn6.length); //1、形参没有默认值,fn6.length:形参的长度;2、形参有默认值,fn6.length是默认值参数的位置
- 参数作用域问题
- 形参所在的小括号是一个单独的作用域,遇到了变量,想看自己作用域下有没有,没有再往上一级找
- 扩展运算符 ...
- ... 可以将数组变成非数组,也可以将非数组变成数组
- let ary=[123];console.log(...ary);
- ... 可以将字符串变成数组
- let str='12345';console.log([...str]);
- ... 可以将类数组变成数组
- function fn(){ return [...arguments].sort() }; fn(3,2,5,4,1,6);
- ... 应用场景
- 求最大值的方法 let ary1 = [1,3,2,31,123,234];
- //eval :eval("Math.max("+ ary1 +")");
- //apply : Math.max.apply(null, ary1);
- //... :Math.max(...ary1);
- 函数的name
- let fn = function(){}; console.log(fn.name); // fn
- 匿名函数name: console.log((function(){}).name); // ''
- bind ----> bound fn
- let obj = {};var fn1=fn.bind(obj);fn1(); console.log(fn1.name); //bound fn
- new Function ----> anonymous
- let f= new Function('n', 'return n');console.log(f.name); //anonymous
- 箭头函数
let fn = function(){let a=1;return a;}let fn = (x) => {let a =1;return a;}
// x=> x; 如果函数体只有一行代码而且是return,可以简写成这样function fn(x){return x;}
- 箭头函数中this问题
- 箭头函数没有this指向,它里面的this是谁----看它上一级作用域中的this(保证上一级函数不是箭头函数 )
let obj = {fn: function(){console.log(this);let f=()=>{console.log(this);}f();},fn1: ()=>{console.log(this);}};obj.fn(); //this==objobj.fn1(); //this==windowdocument.querySelector('#box').onclick=()=>{console.log(this); //window};
- 对象的扩展
- 属性的简洁表示
let a = 'aa', b='bb';let obj = {[a]: 'AAA', //属性,通过变量传值[a+b]: 'AAA+BBB',fn(){},/*fn: function(){}*/};console.log(obj.a);console.log(obj['a']);console.log(obj);
- Object类上的方法
- Object.is();
- console.log(Object.is(NaN, NaN));
//数组去重let arr = [1,2,NaN,NaN,1,3];let newArr = [];arr.forEach((item)=>{var flag = true;for(var i=0;i<newArr.length;i++){if(Object.is(item, newArr[i])){flag = false;}}if(flag){newArr.push(item);}});console.log(newArr);
- Object.assign(obj1, obj2);
- 将obj2合并到obj1上,返回obj1
- Object.getOwnPropertyDescriptor(); //获取对象的属性描述
console.log(Object.getOwnPropertyDescriptor(str, 'length'));console.log(Object.getOwnPropertyDescriptor([1,2,3], 'length'));
- 属性的变量
- for in
- Object.keys()
- 返回值是一个数组,包括对象自身的(私有属性)所有的可枚举的属性;
- Obeject.getOwnPropertyNames()
- 返回值是一个数组,包括对象自身的(私有属性)所有的不可枚举的属性;
- Set 和 Map 数据结构
- Set
- 1、使用构造函数方式创建Set的实例;参数是个数组,返回值是一个Set实例,去重后的类数组;
let set1 = new Set([1,2,3,NaN,NaN,1,2,3,4,5]);console.log(set1);//将Set实例变成数组console.log([...set1]); //1、... 将类数组转化为数组console.log(Array.from(set1)); //2. Array.from() 将类数组转为数组/* 利用set实现数组去重 */function fn(arr){return [...new Set(arr)];}console.log(fn([1,1,1,1,3,3,5,76,4,65]));
- 2、Set原型上的方法(let set = new Set([1,2,3,1,2,3]))
- size 长度
- add() ----增加一项,之前没有才可以加上,加在后面。返回值是当前实例,实现链式写法
- console.log(set.add(5).add(4));
- has() ----判断有没有某一项,返回值是true、false
- console.log(set.has(1));
- delete() ----删除,返回值是true、false
- console.log(set.delete(6));
- console.log(set);
- clear() ----清空,没有返回值,undefined
- console.log(set.clear());
- console.log(set);
let arr1 = [1,2,3,4,5,6];let arr2 = [2,4,6,8,10];//数组并集function bj(arr1,arr2){return [...new Set([...arr1,...arr2])];}bj(arr1,arr2);
//数组交集function jj(arr1,arr2){return arr1.filter((item)=>{return arr2.includes(item);});}jj(arr1,arr2);
//数组差集function cj(arr1,arr2){return bj(arr1,arr2).filter((item)=>{return !jj(arr1,arr2).includes(item);});}cj(arr1,arr2);
var set1=new Set(["z","h","u","f","e","n","g"]);console.log(set1);//遍历set数据的实例只能遍历value值set1.forEach((item,index)=>{//item当前项console.log(item, index);});for(var key of set1.keys()){console.log(key);}for(var val of set1.values()){console.log(val);}for(var en of set1.entries()){console.log(en);}
- Map
- 1.使用构造函数方式创建一个实例
- 2.参数是个数组,数组的每一项都是一个数组,这个数组有两项,第一项作为键key,第二项作为值value
- 3.这里的key键可以是任意数据类型的
var map1=new Map([[1,"a"],["a","A"],[{name:"珠峰"},"珠峰"],[/d+/,"正则"]]);console.log(map1);//方法//get(key)console.log(map1.get("a"));//set(key,value);map1.set(2,"JS");console.log(map1);//delete,has,clearlet ary=[1,2,3,4,5,6];//将数组变成Map//1,[1]//2,[1,2]//3,[1,2,3]//....var map=new Map();ary.forEach((item,index)=>{map.set(index+1,ary.slice(0,index+1))});console.log(map);//forEach(),keys(),values(),entries();map.forEach((val,key,map)=>{//val:值,//key:键//map:原Map实例})for(var key of map.keys()){//key:键}for(var val of map.values()){//val:值,}for (var [key,val] of map.entries()){//val:值,//key:键}