ES_6

严格模式 “use strict”
必须用var声明变量
禁止自定义的函数中的this指向window (自调用函数,就是定义一个构造函数,直接写函数,不使用new去创建一个函数,不使用new的时候函数的this指针指向window);
创建eval()作用域。【非严格模式下,eval()方法里面的参数可以直接相当于外部的全部代码,可以被执行,可能是后台返回的要执行的代码,有可能在传输途径下被篡改。严格模式下,eval的内部数据是私有的,不会污染全局的元素。】
对象不可以有同名属性。

ES5扩展

json对象扩展

JSON.stringify(obj/arr)	//将原生的js对象(数组)转换为json对象(数组)
JSON.parse(json)	//将json对象转换为js对象(数组)

object扩展

1、Object.create(prototype,[descriptors]);
//作用:以指定对象为原型创建新的对象
//为新的对象指定新的属性,对属性进行表述【value:指定属性值;wirtable:标识当前属性值是否可以被修改;configurable:标识当前属性是否可以被删除;enumerable:标识当前属性是否能用for-in枚举,后面三个都是默认为false】
var obj  = {username:'shufang107',age:'21'};
var obj1;
obj1 = Object.create(obj,{
	sex:{
		value:'女',
		writable:'true';
	}
})
2、Object.definepropertise(object,descriptors);
//作用:为指定的对象定义扩展多个属性
//get():用来获取当前属性值的回调函数,就是通过get()方法可以获取扩展属性的值
//set():修改当前属性值触发的回调函数,并且实参是修改后的值。
//存取属性:setter,getter一个用来存值,一个用来取值。
var obj2 = {firstname:'huang',lastname:'shufang'};
Object.definepropertise(obj2,{
fullName:{
	get:function(){ //获取当前属性的值,会自动调用
		console.log("get()");	用来检测调用了几次get方法,会发现惰性调用,只有在				  使用了fullname方法之后才会调用这个方法。
		return this.firstname+" "+this.lastname;
	}
	set:function(data){  //监听扩展属性,data的值就是传入的新的属性值,在扩展属性发上变化的时候才会被调用。
		var names = data.split(" ");
		this.firstname = name[0];
		this.lastname = name[1];
	}
}
})
console.log(obj2.fullName); //此时get方法会被调用一次;
obj2.fullName = "haha huanghuang";  //当fullName的值被修改的时候,set方法存在才可以被修改,如果没有set方法不会被修改。
consloe.log(obj.fulName); //此时的返回值是被修改的值。
3、对象本身两个方法
 get propertyName(){}	用来得到当前属性值的回调函数;
 set propertyName(){}	用来监听当前属性值变化的回调函数;
 //把前面的扩展方法中set function(){} 换成 set fullName(){}

数组的扩展

Array.prototype.indexOf(value); //得到值在数组中的第一个下标,相同值返回的也是第一个
Array.prototype.lastIndexOf(value); //得到值在数组中的最后一个下标
Array.prototype.forEach(function(item,index){}); //遍历数组
Array.prototype.map(function(item,index(){}); //遍历数组返回一个新的数组,返回加工后的值
Array.prototype.map(function(item,index(){}); //遍历过滤出一个新的数组,返回条件为true的值,留下的值满足过滤的条件。

var arr = [1,2,5,3,7,8,3,1,4];
console.log(arr.indexOf(1)); //返回0
console.log(arr.lastindexOf()); //返回7
arr.forEach(function(item,index){
	console.log(item);
});
var arr1 = arr.map(function(item,index){
	return item+10;	
}); //创建一个新的数组arr1来承接新返回的函数。
var arr2 = arr.filter(function(item,index){
	return item > 3;
})

函数的扩展
改变函数中this指向的对象 function.prrototype.bind(obj);
1、call():参数是一个一个直接放;
2、apply():参数放在数组里面来传递;
3、bind();参数传递方式与call()一样;但是这个方法将函数返回,而不会立刻执行这个函数。

var obj = {username:'shufang107'};
function foo(data){
	console.log(this,data);	
}
foo.call(obj,33);
foo.apply(obj,[33]);
var obj2 = foo.bind(obj,33);
//此时的obj2当前的obj函数;而不会立刻执行。

ES_6

let关键字
let 作用
1、与var类似,用于声明一个变量;
let特点
1、在块级作用域内有效
2、不能重复声明变量
3、不会预处理【预解析】,不存在提升
4、存在暂时性死区。在块级作用域下,也需要先声明在访问。1

js引擎机制的预处理:
1、变量声明:只声明不传值;
2、函数的预处理:函数有声明式函数【function Fn(){}】和赋值型函数【var Fn = function(){}】;
在var变量定义之前使用这个变量,因为存在预处理不会报错,但是值为undefined;
函数预处理是将声明式函数先提取出来,之后按顺序执行。

let应用
1、循环遍历加监听
2、使用let取代var是趋势

const关键字
const作用:
1、定义一个常量
const特点
1、不能修改
2、其他特点同let
const应用
1、保存不用改变的变量

变量的解构赋值
1、理解
从对象或数组中提取数据,并赋值给多个变量

//函数解构赋值
let obj = {username:'shufang107';age:21}
//普通赋值,此时是两部赋值
let username = obj.username;
let age = obj.age;
//解构赋值
let{username,age} = obj;
console.log(username);	//打印出username的值 
//注意:解构赋值let创建的变量一定是obj对象里面已经有的属性值,不可以写成 let{username,XXX} 此时的XXX得到的值是undefined;

//数组解构赋值
let arr = [1,2,4,5,7,8];
let[a,b] = arr;
console.log(a,b);	//根据位置来获取值 1,2
let[,,a,b] = arr;
console.log(a,b);	//得到4,5

//普通传递对象参数
function foo(obj){	//参数是一个obj对象
	console.log(obj.username,obj.age);
}
//解构传参
function foo({username,age}){	//解构传参可以直接使用
	consloe.log(username,age);
}

模板字符串
简化字符串的拼接
1、模板字符串必须用 ` `包含
2、变化的部分使用${XXX}定义;

let obj = {username:'shufang107';age:'21'};
let str = "我的名字:"+obj.username+" , 年龄是:"+”obj.age“;  //普通拼接
let str = '我的名字:'$(obj.username),'年龄是:'$(obj.age);

简化对象的写法
1、可以省略同名属性的值
2、可以省略对象里面函数定义的function

let username = 'shufang107';
let age = 21;

let obj = {
	username,
	age,
	getName(){	//普通的是getName = function(){...}
		console.log(this.username);
	}
}

箭头函数的详解
作用:定义匿名函数
基本语法:1、没有参数 ()=>console.log(“xxx”); //()可以省略,
2、一个参数 (i)=>i+2;
3、大于一个参数 (i,j)=> i+j;
4、函数体只有一条语句不用{}大括号,默认为函数的返回值;
5、函数体多条语句,需要用{}包围,需要手动return返回值;
使用场景:多用来定义回调函数
特点:
1、简洁
2、箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候所处的对象就是他的this;
// 普通的函数是,什么元素调用这个函数,函数的this就指向这个元素。
3、扩展理解:箭头函数的this看外层是否有函数;
如果有:外层函数的this就是内部箭头函数的this;
如果没有:则this就是window;

每一个函数有有返回值,如果没有明确指定的时候默认为undefined;
//形参的情况
1、没有形参的时候,()不可以省略;
let fun1 = () =>console.log(“箭头函数”);
fun1(); //调用这个箭头函数
2、只有一个形参的时候,()可以省略;
let fun2 = a =>console.log(a);
fun2(1); //调用箭头函数
3、有两个及两个以上的形参的时候,()不可以省略
let fun3 = (a,b) =>console.log(a+b);
fun3(2,3);
//函数体的情况
1、只有一条语句或者表达式的时候,可以省略{}花括号,语句默认为返回值,但是运算语句加上{}之后就不是默认为返回值,需要手动return返回;
fun4 = (a,b) => a+b;
console.log(fun4(1,2)); //返回3;
fun4 = (a,b) => {a+b}; //加上大括号之后不是返回值了,执行上一句的时候是undefined;所以建议只有一条语句的时候不使用{};
2、两条或多条语句的时候,{}不可以省略

//箭头函数的this指向
let btn = document.getElementById(“btn”); //获取按钮元素
btn.onclick = function(){
alert(“this”);
} //this指向HTML的button元素
btn.onclick = ()=>{console.log(this);} //此时的箭头函数外部没有function函数,所以this指向的是window;
let obj = {
name:“箭头函数”;
getname:function(){
btn.onclick = ()=>{console.log(this);} //此时的箭头函数外面有一个function,所以此时的this与外层函数this指向的对象是一样的。
}
getname2:() =>{
console.log(this); //此时的箭头函数外部没有函数,相当于 obj.getname2 = ()=>{console.log(this);},所以此时外部没有函数,this指向window;
}
}

三点运算符[…]
用途:rest(可变)参数
1、用在函数参数上,用来取代argument【函数的实参的一个伪数组,不可以使用数组的方法比如 forEach遍历】但是三点运算符只能是最后部分的形参参数

function fun(...values){
	console.log(arguments);	 //此时返回的是一个伪数组,控制台显示[...]
	console.log(values);	//此时返回真的实参组成的数组
	values.forEach(function(item,index)){
		console.log(item,index);	//values是一个函数实参形成的真的数组,所以可以调用数组的方法;
		}
}

2、用在数组里面

let arr = [1,6];
let arr1 = [2,3,4,5];
arr = [1,...arr1,6];		//给arr函数从新赋值
console.log(arr);	//[1,6]
console.log(...arr);	//[1,2,3,4,5,6];

形参默认值
当不传入参数时默认使用参数里的默认值

function point(x = 1;y = 2){		//如果形参也没有指定一个值,则不传参数的时候是undefined function(x,y);
	this.x = x;
	this.y = y;	
}

promise对象
理解:
1、promise对象 代表未来某个要发生的事件(通常是异步操作)
2、有了promise对象可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调函数(“回调地狱【嵌套调用、几个不是嵌套的函数的复杂回调关系】”)
3、ES6的Promise是一个构造函数,用来生成promise实例
使用promise基本步骤:
1、创建promise对象

let promise = new Promise((resolve,reject) => {
	//初始化promise状态为pending
	//执行异步操作
	if(异步操作成功){
	resolve(value);		//修改promise的状态为fullfilled
}else{
	reject(errmsg);		//修改promise的状态为reject
}
})

2、调用promise的then();

promise.then(function){
	result => console.log(result),
	errormsg => alert(errorMsg)	
}

promise对象的3个状态:
1、pending:初始化状态
2、fullfilled:成功状态
3、reject:失败状态
应用:
1、使用promise实现超时处理
2、使用promise封装处理ajax请求

//创建promise对象
let promise = new Promise((resolve,reject) => {
//自动初始化promise状态:pending :初始化
console.log('111');
//执行异步操作,通常是发送ajax请求,开启定时器
setTimeout(() => {
	console.log("333");
	resolve();}		//修改promise为fullfilled,
	//如果异步操作成功返回的数据放在resolve的参数中,then中的函数就可以使用这个数据
	2000)
})
console.log('222');

promise.then(() => { //then的两个参数是成功的回调
		console.log("成功了。。。");
	} , () => {//失败的回调
		console.log("失败了。。。");
	})

//实例练习

function getNews(url){ 	//ajax请求的函数,传入需要访问的url
	let promise = new Promise((resolve,reject) => {		//状态:初始化;执行异步任务;
		let xmlHttp = new XMLHttpRequest();	//创建XMLHttpRequest的实例对象 xmlHttp;
		xmlHttp.onreadystarechange = function(){
			if (xml.readState === 4){
				if(xmlHttp.status == 200){		//满足两个状态表示请求成功
					console.log(xmlHttp.responseText);		//打印当前返回的数据
					resolve(xmlHttp.responseText);		//修改promise的状态
				}else{
					reject('请求失败。。。');		//修改成失败的状态
				}	
			}	
		}
	xmlHttp.open('GET',url);
	xmlHttp.send();
	});
return promise;		//因为promise创立在函数内部,只有在调用函数的时候才会被创建;
所以promise对象作为函数返回值才可以被外部使用这个promise对象。
}

getNews(url)
	.then((data) => {	
		//发送请求获得新闻评论的内容,准备url
		let commentsUrl = JSON.parse(data).commentrsUrl;	//获取数据中的共同的url部分
		let url = 'http://localhost:3000' + conmentsUrl;
		//发送请求 
		return getNews(url); 	//将getNews()函数作为返回值,可以避免再次调用原来getNews()函数返回promise对象,之后进行无尽的循环调用,所以返回一个函数返回的
	} , () => {
	})
	.then(() => {} , () => {});		//第二次使用的时候判断其食肉请求成功。

Symbol属性介绍
前言:ES5中的对象属性名都是字符串,容易造成重名,污染环境
symbol:
概念:ES6中的添加的一种原始数据类型symbol()
//原始数据类型:string,number,boolean,null,undefined,对象
特点:
1、symbol属性值对应的值是唯一的,解决命名冲突问题
2、symbol值不能与其他数据进行计算,包括字符串拼串
3、for-in,for-of遍历时不会遍历symbol属性。就是对象的属性遍历的时候跳过symbol属性;
使用:
1、调用symbol函数得到symbol值
//let symbol = Symbol();
//let obj = {};
//obj[symbol] = ‘hello’;
//symbol只是创建一个属性,obj[symbol]是将这个属性放到这个对象中

let targetData = {
	[symbol.iterator]:function(){}	//是对象的一个属性
}

2、传参标识
let symbol1 = Symbol();
let symbol2 = Symbol();
//没有参数的时候,虽然控制台打印出来的symbol1 和symbol2是一样的Symbol();但是实际上是不一样的
//console.log(symbol1 == symbol2); 返回false
let symbol1 = Symbol(‘one’);
let symbol2 = Symbol(‘two’);
//console.log(symbol1,symbol2)是 Symbol(‘one’),Symbol(‘two’) 通过参数来区别不同的Symbol;
3、内置Symbol值:此时symbol相当于一个对象;
除了定义自己使用的symbol 值之外,还有11个内置的symbol值;

symbol内置对象
iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制
作用:
1、为各种数据机构提供一个统一的,简便的访问接口
2、使得数据结构的成员能够按照某种次序排列
3、ES6创造了一种新的遍历命令(for-of)循环,iterator接口主要提供for—of循环
工作原理:
1、创建一个指针对象(遍历器对象),指向数据结构的起始位置。
2、第一次调用next方法,指针自动指向数据结构的第一个成员
3、接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员
4、每次调用next指针返回的是一个包含value和done的对象{value:当前成员的值【遍历完之后是undefined】,done:布尔值【遍历完为true,没有遍历完是false】}
原生具备iterator接口的数据(可以使用for_of遍历)
扩展理解:
1、当使用for-of遍历目标数据的时候,该数据会自动去找Stmbol.iterator属性
//Array、argument、字符串、set容器、map容器

//模拟指针对象【遍历器对象】
function myIterator(arr){	//这个函数就是iterator接口
	let nextIndex = 0;	//记录指针的位置
	return{
		next:function(){
			return nextIndex < arr.length ? {value:arr[nextIndex++],done:false}	
		}
	}
}
let arr = [1,4,2,4,'asd'];	//准备一个数据
let iteratorObj = myIterator(arr);		//将函数的返回值赋值给一个对象
console.log(iteratorObj.next());
console.log(iteratorObj.next());
console.log(iteratorObj.next());		//重复调用这个方法,知道指针指向最后一个元素。
//将iterator接口不熟到指定数据的类型上,可以使用for-of去循环遍历
默认可以使用的数据类型:
//数组
let arr = [1,2,3,4,5]
for(let i of arr){
	console.log(i);
}
//let str = 'abcdef';
for(let i for str){
	console.log(i);
}
//遍历函数的argument伪数组
function fun(){
	for(let i for arguments){
		console.log(i);
	}
}

//以上的for of遍历的数据结构中没有对象,所以对象需要使用for of 循环遍历的时候就要调用Symbol.iterator接口

//为对象添加这个iterator方法之后就可以进行遍历了
let targetData = {
	[symbol.iterator]:function(){
		let nextIndex = 0;
		return function(){
			next:function(){
				return nextText < this.length ? {value:this[indexIndex++],done:false}:{value:undefined,done:ture};	
			}	
		}
	}
}

generator函数简介
概念:
1、ES_6提供的解决异步编程的方案之一
2、generator函数是一个状态机,内部封装了不同状态的数据
3、用来生成遍历器对象
4、可暂停函数(惰性求值),yield 可暂停,next方法可以启动。每次返回的是yield后的表达式的结果
特点:
1、function 与函数名之间有一个星号(*)
2、内部用yield表达式来定义不同的状态;

function* generatorexample(){
let result = yield ‘hello’; //状态就是 hello
yield ‘generator’; //状态是generator
}

3、generator函数返回的是指针对象(iterator指针,调用next方法才开始执行),不会执行函数内部的逻辑;
console.log(MG.next()); //{value:开始执行,done:false};
//next方法返回的是遍历器iterator 返回的对象
在这里插入图片描述
4、调用next 方法函数内部逻辑开始执行,遇到yield表达式之后停止执行,next方法返回{value:yield后的表达式结果、undefined,done:false/true}
5、暂停后再次调用next方法会从上一次的yield表达式开始执行。
6、yield语句返回结果通常为undefined,调用next方法时候传入的参数会作为启动时候yield语句的返回值。
//下面的例子是使用generator方法对promise方法发送请求的修改
在这里插入图片描述

async函数详解及应用
概念:
真正解决异步回调的问题,同步流程表达异步操作
本质:
是Generator语法的升级
语法:
async function foo(){
await 异步操作;
await 异步操作;
}
特点:
1、不需要像generator去调用next方法,当前的异步操作完成之后自动往下执行;
2、返回的总是promise对象【generator方法也是返回promise对象】,可以用.then()方法执行下一步操作;
3、async 取代generator函数符号*,await取代generator函数的yield
4、语法上更加明确,使用简单。

//同样异步获取新闻内容例子
//下面是发送请求的函数
async function getNews(url){
	return new Promise((resolve , reject) => {
		$.ajax({
			method:'GET';		
			url,		//ES6中对象的属性与传入的参数一样的话可以省略这个属性的值;
			success: data => resolve(data),	//resolve函数总是返回他的参数,所以将获取的data数据当成参数返回;
			error:error => reject()	//请求失败
		})
	})
}
// async函数
async function test(){
	let result = await getNews("http://localgost:3000/news?id=1");	//await语句执行之后返回的是promise对象,如果没有参数的时候这个打印这个对象的值是undefined
	//await语句执行后有传入参数,则这个promise对象的返回值是这个参数的值。
	console.log(result);
	result = await getNews('http://localgost:3000' + result.comments);	//第二次发送请求,获取新闻的评论值。
}
test();	//调用这个async函数。执行异步操作。

class类使用详解
1、通过class定义类、实现类的继承
2、在类中通过constructor定义构造方法 //类定义的方法会放在calss的原型对象上,普通函数和构造函数都是放在原型对象上
3、通过new来创建类的实例
4、通过extends来实现类的继承
5、通过super调用父类的构造方法
6、重写从父类中继承的一般方法

class person{
	constructor(name,age){
		this.name = name;
		this.age = age;	
	}
	showname(){	//类中不需要使用function 来定义方法
		console.log(this.name);
	}
}
let person = new Person('shufang107',21);	//定义一个person类
//子类继承父类
class oneperson extends Person{
	constructor(name,age,salary){
		super(name,age);		//继承父类的构造函数时需要使用super方法且进行传参,不然后返货undefined;
		this.salary = salary;		//这个元素是子类自己所有的元素
	}
	showName(){		//子类的方法从写,就是父类上也有这个方法
					//但是当子类和父类都有一个同名的方法的时候,会调用子类的这个方法二不去执行父类的同名方法。
					//但是子类没有这个方法的时候去调用,会通过原型链去找父类的这个方法来执行
	}
}

字符串、数组的扩展
//字符串扩展
inculdes(str):判断是否含有指定的字符串
startsWith(str) :判断是否以指定的字符串开头
endWith(str):判断是否以指定的字符串结尾
repeat(count):将字符串重复指定的次数 var str = ‘we’;str.repat(3);//输出 wewewe

//数值的扩展
1、二进制与八进制的表示方法:二进制0b ,八进制 0o; //转换为10进制
console.log(0b1010); //10
console.log(0o34); //28
2、Number.isFinite(i); //判断是否是有限大的数
3、Number.isNaN(i); //判断是否为NaN
4、Number.isInteger(i); //判断是否为整数
5、Number.parseInt(str); //将字符串强制转换为数值类型
6、Math.trunc(i); //直接去除小数部分

//数组的扩展
1、Array.from(v); //将伪数组对象或可遍历的对象转换为真的数组
函数的参数、获取的页面元素等等
2、Array.of(v1,v2,v3); 将一系列值转换为数组
3、find(function(value,index,arr)){return true}; //找出第一个满足条件返回true的元素,判断的条件是函数体内部语句。
4、findIndex(function(value,index,arr)){return true}; //找出第一个满足条件返回true的元素的下标
在这里插入图片描述
对象方法的扩展
1、Object.is(v1,v2) //判断2个数据是否完全相等,按照字符串来判断
Object.is(0,-0); //false
Object.is(NaN,NaN); //true
console.log(0 == -0); //true
2、Object.assign(target,source1,source2…); //将源对象的属性复制到目标对象上

let obj = {};
let obj1 = {username:'shufang107',age:21}
Object.assign(obj,obj1,obj2);

3、直接操作_proto_属性; //可以将一个对象1设置为对象2的原型对象,此时对象2可以访问对象1的属性

let obj1 = {name : 'shufang107'};
let obj2 = {};
obj2._proto_ = obj1;
console.log(obj2.name);	//可以得到obj1的属性值

深度克隆

let obj1 = {username:'shufang107' , age:21};
let obj2 = obj1;	//对象1赋值给对象2赋=赋值是对象的引用,而不是这个对象的内存元素
		//相当于赋值的是一个指向对象1的指针,所以赋值后对象1 和对象2操作元素会互相影响。
//但是如果不是对象类型的话,只是单纯的值类型或者字符串类型就不会影响,因为复制是新开辟一个内存地址存放复制的元素。
console.log(obj1);

在这里插入图片描述

拷贝数据
基本数据类型:
拷贝后会生成一份新的数据,修改拷贝以后的数据不会影响原来的数据
对象 、数组:
拷贝后不会生成新的数据,而拷贝的是引用,修改拷贝后的数据会影响原来的数据
拷贝数据的方法:
1、直接赋值给一个变量: //浅拷贝,会影响原数据
2、Object.assign(); //浅拷贝
3、Array.prototype.concat(); //浅拷贝,会影响数组里面的对象元素
let arr1 = [1,2,{name:‘shufang’}];
let arr2 = [4,5];
arr1.concat(arr2); //生成一个新的数组
Array.prototype.slice(); //浅拷贝
JSON.parse(JSON.stringfy()); //深度拷贝,但是元素里面不可以有函数
浅拷贝(对象、数组):拷贝的是引用,修改拷贝以后会影响原数据,使原数据不安全
深度拷贝:拷贝时生成新数据,修改数据后不会改变原来的数据

如何进行深度拷贝:
1、拷贝数据里面有对象:
继续遍历这个对象,直到拿到的是基本数据类型的时候才开始拷贝,此时就是深度拷贝
2、没有数组和对象
//知识储备
1、判断数据类型
typeof返回数据类型:string、Number、Boolean、Undefined、Object、function
Object.prototype.toString.call(obj)
// 使用Object.prototype原型链上的toString()方法将call绑定的元素转换为制服穿
for in循环:对象返回的是属性名,数组返回的是index下标

//定义检测数据类型的功能函数
function checkType(target){
	return Object.prototype.toString.call(target).slice(8,-1);
	//因为上面的toString方法返回的是字符串[Object Array],我们只需要后面的类型
}
function conle(target){	//初始化拷贝的数据类型
	let result,targettype = checkedType(targrt);	//判断变量result这个是最终克隆的数据
	if(targettype === 'Object'){		//判断如果当前拷贝的是对象的话就先生成一个空对象
		result = {};
	}else if (targettype === 'Array'){		//同对象一样
		result = [];
	}else{
		return target;	//如果当前拷贝的不是对象和函数就直接返回这个元素。	
	}
//遍历目标数据,前面只是判断这个要复制的对象是什么,没有进行遍历,
	for(let i in target){
		//获取遍历数据结构的每一项值
		let value = target[i];
		//判断目标结构里的每一项的是否是对象/数组
		if(checkType(value) === 'Object' || checkType(value) === 'Array'){
			//如果是对象或者数组,继续遍历获取到value的值
		 	result[i] = clone(value);
		}else{
			result[i] = value;//如果当前的元素不是对象或者数组,是基本数据类型
		}	
	}
	return result;
}

set容器map容器
set容器:
在这里插入图片描述

for of
使用set和for of 为数组去重
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值