学习ES6笔记[尚硅谷教育一]
01.严格模式
<!-- 1. 理解: * 除了正常运行模式(混杂模式),ES5添加了第二种运行模式:"严格模式"(strict mode)。 * 顾名思义,这种模式使得Javascript在更严格的语法条件下运行 2. 目的/作用 * 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为 * 消除代码运行的一些不安全之处,为代码的安全运行保驾护航 * 为未来新版本的Javascript做好铺垫 3. 使用 * 在全局或函数的第一条语句定义为: 'use strict'; * 如果浏览器不支持, 只解析为一条简单的语句, 没有任何副作用 4. 语法和行为改变 * 必须用var声明变量 * 禁止自定义的函数中的this指向window * 创建eval作用域 * 对象不能有重名的属性 --> <script type="text/javascript"> 'use strict' var username='coke' console.log(username) function Person(name,age){ this.name=name; this.age=age } new Person('coke',26) var str='NBA' eval('var str="CBA";alert(str)') alert(str) </script>
02.JSON对象
<!-- 1.JSON.stringify(obj/arr) *js对象(数组)转换为js对象(数组) 2.JSON.parse(json) *json对象(数组)转换为js对象(数组) --> <script> var obj={username:'kobe'}; obj=JSON.stringify(obj); console.log(typeof obj); obj=JSON.parse(obj); console.log(typeof obj); //var a='aaa' //var b="bbb" </script>
03.Object扩展
<!-- ES5给Object扩展了好一些静态方法, 常用的2个: 1. Object.create(prototype, [descriptors]) * 作用: 以指定对象为原型创建新的对象 * 为新的对象指定新的属性, 并对属性进行描述 value : 指定值 writable : 标识当前属性值是否是可修改的, 默认为false configurable: 标识当前属性是否可以被删除 默认为false enumerable: 标识当前属性是否能用for in 枚举 默认为false 2. Object.defineProperties(object, descriptors) * 作用: 为指定对象定义扩展多个属性 * get :用来获取当前属性值得回调函数 * set :修改当前属性值得触发的回调函数,并且实参即为修改后的值 * 存取器属性:setter,getter一个用来存值,一个用来取值 --> <script> var obj={username:'coke',age:'26'}; var obj1={} obj1=Object.create(obj,{ sex:{value:'男', writable:true, configurable:true, enumerable:true } }); console.log(obj1.sex) obj1.sex='女' console.log(obj1.sex) // delete obj1.sex // console.log(obj1) for(var i in obj1){ console.log(i) } //Object.defineProperties(object,descriptors) var obj2={firstName:'Kobe',lastName:'bryant'}; Object.defineProperties(obj2,{ fullName:{ get:function(){//获取扩展属性的值,获取扩展属性的get方法自动调用 console.log('get()') return this.firstName+' '+this.lastName; }, set:function(data){//监听扩展属性,当扩展属性发生变化的时候会自动调用,自动调用后会将变化的值作为实参 console.log('set()',data); var names=data.split(' '); this.firstName=names[0]; this.lastName=names[1]; } } }) console.log(obj2) console.log(obj2.fullName); obj2.fullName='tim duncan' console.log(obj2.fullName) </script>
04.Object扩展2
<!-- 对象本身的两个方法: *get propertyName(){}用来得到当前属性值得回调函数 *set propertyName(){} 用来监视当前属性值变化的回调函数 --> <script> var obj={ fisrtName:'curry', lastName:'stephen', get fullName(){ return this.firstName+' '+this.lastName ; }, set fullName(data){ var names=data.split(' '); this.firstName=names[0]; this.lastName=names[1]; } } console.log(obj); obj.fullName='kebo bryant' console.log(obj.fullName) </script>
05.数组遍历
<!-- 1. Array.prototype.indexOf(value) : 得到值在数组中的第一个下标 2. Array.prototype.lastIndexOf(value) : 得到值在数组中的最后一个下标 3. Array.prototype.forEach(function(item, index){}) : 遍历数组 4. Array.prototype.map(function(item, index){}) : 遍历数组返回一个新的数组,返回加工之后的值 5. Array.prototype.filter(function(item, index){}) : 遍历过滤出一个新的子数组, 返回条件为true的值 --> <script> /*需求: 1. 输出第一个6的下标 2. 输出最后一个6的下标 3. 输出所有元素的值和下标 4. 根据arr产生一个新数组,要求每个元素都比原来大10 5. 根据arr产生一个新数组, 返回的每个元素要大于4 */ arr=[2,1,3,4,5,2,8,4,1] console.log(arr.indexOf(4)); console.log(arr.lastIndexOf(4)); arr.forEach(function(item,index){ console.log(item,index) }) var arr1=arr.map(function(item,index){ return item+10; }); console.log(arr1,arr) var arr2=arr.filter(function(item,index){ return item>3 }) console.log(arr,arr2) </script>
06.Function扩展
<!-- 1. Function.prototype.bind(obj) : * 作用: 将函数内的this绑定为obj, 并将函数返回 2. 面试题: 区别bind()与call()和apply()? * 都能指定函数中的this * call()/apply()是立即调用函数 * bind()是将函数返回 --> <script type="text/javascript"> var obj={username:'kobe'}; function foo(){ console.log(this) } console.log(foo(obj)) console.log(foo.call(obj)) console.log(foo.apply(foo)) function foo2(data){ console.log(this,data) } // console.log(foo2.call(obj,33))//直接从第二个参数开始,依次传入 // console.log(foo2.apply(obj,[22]))//第二个参数必须是数组,传入放在数组里 //bind的特点:绑定完this不会立即调用当前的函数,而是将函数返回 //bind传参的方式同call一样 // var bar=foo.bind(obj) // console.log(bar) // bar() //foo2.bind(obj,33)() setTimeout(function(){ console.log(this) }.bind(obj),1000) </script>
07.let关键字
<button >按钮1</button> <button >按钮2</button> <button >按钮3</button> <script type="text/javascript"> let username='kobe'; console.log(username); let btns=document.getElementsByTagName('button'); for(let i=0;i<btns.length;i++){ var btn=btns[i]; /*(function(i){ btn.onclick=function(){ alert(i);} })(i)*/ btn.onclick=function(){ alert(i);} } </script>
08.ES6字符串简写
<script> let username='kobe'; let age=39; let obj={ username,//同名的属性可以省略不写 age, getName(){//可以上略函数的function return this.username } } console.log(obj) console.log(obj.getName()) </script>
09.箭头函数
<button id="btn1">测试箭头函数this_1</button> <button id="btn2">测试箭头函数this_2</button> <!-- * 作用: 定义匿名函数 * 基本语法: * 没有参数: () => console.log('xxxx') * 一个参数: i => i+2 * 大于一个参数: (i,j) => i+j * 函数体不用大括号: 默认返回结果 * 函数体如果有多个语句, 需要用{}包围,若有需要返回的内容,需要手动返回 * 使用场景: 多用来定义回调函数 * 箭头函数的特点: 1、简洁 2、箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在的对象就是它的this 3、扩展理解: 箭头函数的this看外层的是否有函数, 如果有,外层函数的this就是内部箭头函数的this, 如果没有,则this是window。 --> <script> // let fun=function(){ // console.log('我是箭头函数') // } let fun=()=>console.log('我是箭头函数') fun(); //形参的情况 //1、没有形参的时候 let fun1=()=>console.log('我是箭头函数'); fun1(); //2、只有一个形参的时候()可以省略 let fun2=a=>console.log(a); fun2('aaa'); //3、两个及两个以上的形参的时候()不能省略 let fun3=(x,y)=>console.log(x,y) fun3(25,36) //函数体的情况 //1、函数体只有一条语句或者是表达式的时候{}可以省略-->会自动返回语句执行的结果或者是表达式的结果 let fun4=(x,y)=>x+y; console.log(fun4(24,36)); //2.函数体不止一条语句或者是表达式的情况{}不可以省略 let fun5=(x,y)=>{ console.log(x,y); return x+y; } console.log(fun5(35,49)); let btn1=document.getElementById('btn1'); let btn2=document.getElementById('btn2'); btn1.onclick=function(){ console.log(this) } //let that=this; var obj={ username:'箭头函数', getName:()=>{ btn2.onclick=()=>{ console.log(this) }; } }; obj.getName(); </script>
10.点点运算符
<!-- 1. rest(可变)参数 * 用来取代arguments 但比 arguments 灵活,只能是最后部分形参参数 function fun(...values) { console.log(arguments); arguments.forEach(function (item, index) { console.log(item, index); }); console.log(values); values.forEach(function (item, index) { console.log(item, index); }) } fun(1,2,3); 2. 扩展运算符 let arr1 = [1,3,5]; let arr2 = [2,...arr1,6]; arr2.push(...arr1); --> <script> function foo(a,...value){ console.log(arguments); //arguments.callee(); console.log(value) // arguments.forEach(function(item,index){ // console.log(item,index); // }) value.forEach(function(item,index){ console.log(item,index); }) } foo(2,65,33,45); let arr=[1,6]; let arr1=[2,3,4,5]; arr=[1,...arr1,6]; console.log(arr) console.log(...arr) </script>
11.promise函数
<!-- 1. 理解: * Promise对象: 代表了未来某个将要发生的事件(通常是一个异步操作) * 有了promise对象, 可以将异步操作以同步的流程表达出来, 避免了层层嵌套的回调函数(俗称'回调地狱') * ES6的Promise是一个构造函数, 用来生成promise实例 2. 使用promise基本步骤(2步): * 创建promise对象 let promise = new Promise((resolve, reject) => { //初始化promise状态为 pending //执行异步操作 if(异步操作成功) { resolve(value);//修改promise的状态为fullfilled } else { reject(errMsg);//修改promise的状态为rejected } }) * 调用promise的then() promise.then(function( result => console.log(result), errorMsg => alert(errorMsg) )) 3. promise对象的3个状态 * pending: 初始化状态 * fullfilled: 成功状态 * rejected: 失败状态 4. 应用: * 使用promise实现超时处理 * 使用promise封装处理ajax请求 let request = new XMLHttpRequest(); request.onreadystatechange = function () { } request.responseType = 'json'; request.open("GET", url); request.send(); --> <script> /* //创建promise对象 let promise=new Promise((resolve,reject)=>{ //初始化promise状态;pending:初始化 console.log('111') //执行异步操作,通常是发送ajax请求,开启定时器 setTimeout(()=>{ console.log('333'); //根据异步任务的返回结果来去修改promise的状态 //异步任务执行成功 //resolve('哈哈');//修改promise的状态为 fullfilled:成功的状态 //异步任务执行失败 reject('555');//修改promise的状态为 rejected 失败的状态 },2000) }) console.log('222'); promise .then((data)=>{//成功的回调 console.log(data,'成功了.....'); },(error)=>{//失败的回调 console.log(error,'失败了....') }, ) */ //定义获取新闻的功能函数 function getNews(url){ let promise=new Promise((resolve,reject)=>{ //状态:初始化 //执行异步任务 //创建xmlHttp实例对象 let xmlHttp=new XMLHttpRequest(); //绑定监听 readyState xmlHttp.onreadystatechange=function(){ if(xmlHttp.readyState===4){//请求成功 if(xmlHttp.status===200){ // console.log(xmlHttp.responseText); //修改状态 resolve(xmlHttp.responseText);//修改promise的状态为成功的状态 }else{//请求失败 reject('暂时没有新闻内容!!'); } } }; //open设置请求的方式以及url xmlHttp.open('GET',url); // xmlHttp.send() }) return promise } getNews('http://localhost:3000/news?id=2') .then((data)=>{ console.log(data) //发送请求获取评论内容准备url let commentsUrl=JSON.parse(data).commentsUrl; let url='http://localhost:3000'+commentsUrl; //发送请求 return getNews(url); }, (error)=>{ console.log(error) }) .then((data)=>{ console.log(data) }, ()=>{ }) </script>
12.symbol用法
<!-- 前言:ES5中对象的属性名都是字符串,容易造成重名,污染环境 Symbol: 概念:ES6中的添加了一种原始数据类型symbol(已有的原始数据类型:String, Number, boolean, null, undefined, 对象) 特点: 1、Symbol属性对应的值是唯一的,解决命名冲突问题 2、Symbol值不能与其他数据进行计算,包括同字符串拼串 3、for in, for of遍历时不会遍历symbol属性。 使用: 1、调用Symbol函数得到symbol值 let symbol = Symbol(); let obj = {}; obj[symbol] = 'hello'; 2、传参标识 let symbol = Symbol('one'); let symbol2 = Symbol('two'); console.log(symbol);// Symbol('one') console.log(symbol2);// Symbol('two') 3、内置Symbol值 * 除了定义自己使用的Symbol值以外,ES6还提供了11个内置的Symbol值,指向语言内部使用的方法。 - Symbol.iterator * 对象的Symbol.iterator属性,指向该对象的默认遍历器方法(后边讲) --> <script> //创建symbol属性值 let symbol=Symbol(); console.log(symbol); let obj={username:'kobe',age:39}; obj[symbol]='hello'; console.log(obj); let symbol2=Symbol('one'); let symbol3=Symbol('two'); console.log(symbol2===symbol3); console.log(symbol2,symbol3) //可以去定义常量 const Person_key=Symbol('person_key'); console.log(Person_key); const myIterable={}; myIterable[Symbol.iterator]=function*(){ yield 1; yield 2; yield 3; }; console.log([...myIterable]) </script>
13.Iterator对象
<!-- 概念: iterator是一种接口机制,为各种不同的数据结构提供统一的访问机制 作用: 1、为各种数据结构,提供一个统一的、简便的访问接口; 2、使得数据结构的成员能够按某种次序排列 3、ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。 工作原理: - 创建一个指针对象(遍历器对象),指向数据结构的起始位置。 - 第一次调用next方法,指针自动指向数据结构的第一个成员 - 接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员 - 每调用next方法返回的是一个包含value和done的对象,{value: 当前成员的值,done: 布尔值} * value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束。 * 当遍历结束的时候返回的value值是undefined,done值为false 原生具备iterator接口的数据(可用for of遍历) 1、Array 2、arguments 3、set容器 4、map容器 5、String 。。。 --> <script> //模拟指针对象(遍历器对象) function myIterator(arr){//iterator接口 let nextIndex=0;//记录指针的位置 return {//遍历器对象 next:function(){ return nextIndex<arr.length?{value:arr[nextIndex++],done:false}:{value:undefined,done:false} //return {value:arr[nextIndex++],done:false} } } } let arr=[1,4,65,'abc']; let iteratorObj=myIterator(arr); console.log(iteratorObj.next()) console.log(iteratorObj.next()) console.log(iteratorObj.next()) console.log(iteratorObj.next()) console.log(iteratorObj.next()) console.log(iteratorObj.next()) //将Iterator接口部署到指定的数据类型上,可以使用for of 去循环遍历 //数组,字符串,arguments,set容器。map容器 for (let i of arr){ console.log(i) } let str ='abcdef'; for(let i of str){ console.log(i) } function fun(){ for(let i of arguments){ console.log(i); } } fun(1,4,5,'abc') //等同于在指定的数据内结构上部署了Iterator接口 //当使用for of 去遍历某一个数据结构的时候,首先去找symbol.iterator,找到了就去遍历,没有找到的话不能遍历 xxx is not iterable let targetData={ [Symbol.iterator]:function(){ let nextIndex=0;//记录指针的位置 return {//遍历器对象 next:function(){ return nextIndex<this.length?{value:this[nextIndex++],done:false}:{value:undefined,done:false} //return {value:arr[nextIndex++],done:false} }} } } //使用三点运算符,结构赋值,默认去调用iteartor接口 let arr2=[1,6] let arr3=[2,3,4,5] arr2=[1,...arr3,6] console.log(arr2) let [a,b]=arr2 console.log(a,b) </script>
14.generator函数
<!-- Generator函数 概念: 1、ES6提供的解决异步编程的方案之一 2、Generator函数是一个状态机,内部封装了不同状态的数据, 3、用来生成遍历器对象 4、可暂停函数(惰性求值), yield可暂停,next方法可启动。每次返回的是yield后的表达式结果 特点: 1、function 与函数名之间有一个星号 2、内部用yield表达式来定义不同的状态 例如: function* generatorExample(){ let result = yield 'hello'; // 状态值为hello yield 'generator'; // 状态值为generator } 3、generator函数返回的是指针对象(接11章节里iterator),而不会执行函数内部逻辑 4、调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true} 5、再次调用next方法会从上一次停止时的yield处开始,直到最后 6、yield语句返回结果通常为undefined, 当调用next方法时传参内容会作为启动时yield语句的返回值。 --> <script src="./js/jquery.js"></script> <script> function *myGenerator(){ console.log('开始执行') let result= yield 'hello'; console.log(result) console.log('暂停后,再次执行') yield 'generator'; console.log('遍历完毕,结束'); return "返回结果" } let MG= myGenerator();//返回的指针对象 console.log(MG) console.log(MG.next()); console.log(MG.next('qqq')); console.log(MG.next()); //对象的symbol.iterator属性 指向遍历器对象 let obj={username:'kobe',age:39}; obj[Symbol.iterator]=function *myTest(){ yield 1 yield 2 yield 3 } for (let i of obj){ console.log(i) } // 对象的symbol.iterator属性 指向遍历器对象 // 案例练习 /* * 需求: * 1、发送ajax请求获取新闻内容 * 2、新闻内容获取成功后再次发送请求,获取对应的新闻评论内容 * 3、新闻内容获取失败则不需要再次发送请求。 * * */ function getNews(url){ $.get(url,function(data){ console.log(data) let url='http://localhost:3000'+data.commentsUrl; SX.next(url); }) } function *sendXml(){ let url=yield getNews('http://localhost:3000/news?id=2') yield getNews(url) } //获取遍历器对象 let SX=sendXml(); SX.next(); </script>
15.async函数
<!-- async函数(源自ES2017) 概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作 本质: Generator的语法糖 语法: async function foo(){ await 异步操作; await 异步操作; } 特点: 1、不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行 2、返回的总是Promise对象,可以用then方法进行下一步操作 3、async取代Generator函数的星号*,await取代Generator的yield 4、语意上更为明确,使用简单,经临床验证,暂时没有任何副作用 --> <script> /* //async 基本使用 async function foo(){ return new Promise(resolve=>{ // setTimeout(function(){ // resolve(); // },2000) setTimeout(resolve,2000); }) } async function test(){ console.log('开始执行',new Date().toTimeString()); await foo(); console.log('执行完毕',new Date().toTimeString()); } test(); */ /* //async 里await返回值 function test2(){ return 'xxxx' } async function asyncPrint(){ // let result=await test2() let result=await Promise.resolve('promise'); console.log(result) result=await Promise.reject('失败了.....') console.log(result) } asyncPrint(); */ //获取新闻内容 async function getNews(url){ return new Promise((resolve,reject)=>{ $.ajax({ method:'GET', url, success:data=>resolve(data), error:error=>resolve(false) // success:function(data){ // resolve(); // }, // error:function(error){ // reject(); // } }) }) } async function sendXml(){ let result= await getNews('http://localhost:3000/news?id=2'); console.log(result) if (!result){alert('暂时没有新闻推送...');return;} result=await getNews('http://localhost:3000'+result.commentsUrl) console.log(result) } sendXml() </script>
16.class
<!-- 1. 通过class定义类/实现类的继承 2. 在类中通过constructor定义构造方法 3. 通过new来创建类的实例 4. 通过extends来实现类的继承 5. 通过super调用父类的构造方法 6. 重写从父类中继承的一般方法 --> <script> /* function Person(name,age){ this.name=name; this.age=age; } let person=new Person('kobe',39); console.log(person) */ //定义一个人物的类 class Person{ //类的构造方法 constructor(name,age){ this.name=name; this.age=age; } //类的一般方法 showName(){ console.log('调用父类的方法') console.log(this.name,this.age) } } let person =new Person('kobe',39); console.log(person); person.showName(); //子类 class StarPerson extends Person{ constructor(name,age,salary){ super(name,age);//调用父类的构造方法 this.salary=salary; } //父类方法重写 showName(){ console.log('调用子类的方法') console.log(this.name,this.age,this.salary) } } let p1=new StarPerson('wade',36,10000000); console.log(p1); p1.showName() </script>
17.数字进制
<!-- 1. 二进制与八进制数值表示法: 二进制用0b, 八进制用0o 2. Number.isFinite(i) : 判断是否是有限大的数 3. Number.isNaN(i) : 判断是否是NaN 4. Number.isInteger(i) : 判断是否是整数 5. Number.parseInt(str) : 将字符串转换为对应的数值 6. Math.trunc(i) : 直接去除小数部分 1. includes(str) : 判断是否包含指定的字符串 2. startsWith(str) : 判断是否以指定字符串开头 3. endsWith(str) : 判断是否以指定字符串结尾 4. repeat(count) : 重复指定次数 --> <script> console.log(0b1010);//10 console.log(0o56);//46 console.log(Number.isFinite(Infinity)); console.log(Number.isNaN(NaN)); console.log(Number.isInteger(123.12)); console.log(Number.isInteger(123.0)); console.log(Number.parseInt('123abc123')); console.log(Number.parseInt('a123sd123')); console.log(Math.trunc(123.123)); let str='abcde' console.log(str.includes('a')) console.log(str.startsWith('a')) console.log(str.endsWith('e')) console.log(str.repeat(2)) </script>
18.数组扩展
<!-- 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的元素下标 --> <h1>你好,世界!</h1> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <script> let btns=document.getElementsByTagName('button'); Array.from(btns).forEach(function(item,index){ console.log(item) }) let arr=Array.of(1,4,'aba',true); console.log(arr) let arr2=[2,3,4,2,5,7,3,6] let result=arr2.findIndex(function(item,index){ return item>4; }) console.log(result) </script>
19.对象扩展
<!-- 1. Object.is(v1, v2) * 判断2个数据是否完全相等 2. Object.assign(target, source1, source2..) * 将源对象的属性复制到目标对象上 3. 直接操作 __proto__ 属性 let obj2 = {}; obj2.__proto__ = obj1; --> <script> console.log(0==-0);//true console.log(NaN==NaN);//false console.log(Object.is(0,-0));//false console.log(Object.is(NaN,NaN));//true let obj={}; let obj1={username:'anverson',age:42}; let obj2={sex:'男'}; Object.assign(obj,obj1,obj2); console.log(obj); </script>
20.对象拷贝
<!-- 1、数据类型: * 数据分为基本的数据类型(String, Number, boolean, Null, Undefined)和对象数据类型 - 基本数据类型: 特点: 存储的是该对象的实际数据 - 对象数据类型: 特点: 存储的是该对象在栈中引用,真实的数据存放在堆内存里 2、复制数据 - 基本数据类型存放的就是实际的数据,可直接复制 let number2 = 2; let number1 = number2; - 克隆数据:对象/数组 1、区别: 浅拷贝/深度拷贝 判断: 拷贝是否产生了新的数据还是拷贝的是数据的引用 知识点:对象数据存放的是对象在栈内存的引用,直接复制的是对象的引用 let obj = {username: 'kobe'} let obj1 = obj; // obj1 复制了obj在栈内存的引用 2、常用的拷贝技术 1). arr.concat(): 数组浅拷贝 2). arr.slice(): 数组浅拷贝 3). JSON.parse(JSON.stringify(arr/obj)): 数组或对象深拷贝, 但不能处理函数数据 4). 浅拷贝包含函数数据的对象/数组 5). 深拷贝包含函数数据的对象/数组 --> <script> /* //不会影响元数据 let str='abcd'; let str2=str; console.log(str2); str2=''; console.log(str); let bool1=true; let bool2=bool1; bool2=false; console.log(bool1); let obj={username:'kobe',age:39}; let obj1=obj; console.log(obj1); obj1.username='wade'; console.log(obj.username); //拷贝数组/对象 没有生成新的数据而是复制了一份引用。 let arr=[1,4,{username:'kobe',age:39}]; let arr2=arr; arr[0]='abcd'; console.log(arr,arr2); */ /* *拷贝数据: * 基本数据类型: * 拷贝后会生成一份新的数据,修改拷贝以后的数据不会影响元数据 * 对象/数组 * 拷贝后不会生成新的数据,而是拷贝是引用。修改拷贝以后的数据会影响原来的数据 * 拷贝数据的方法 * 1.直接赋值给一个变量 //浅拷贝 * 2.Object.assign() //浅拷贝 * 3.Array.prototype.concat()//浅拷贝 * 4.Array.prototype.slice()//浅拷贝 * 5.JSON.parse(JSON.stringify())//深拷贝(深度克隆),拷贝的数据里不能有函数 ,处理不了 * 浅拷贝(对象/数组): * 特点:拷贝的引用,修改拷贝以后的数据会影响原数据 * 深拷贝(深度克隆) * 特点:拷贝的时候生成新数据,修改拷贝以后的数据不会影响原数据 * */ /* let obj={username:'kobe'}; let obj2=Object.assign(obj); console.log(obj2);//{username: "kobe"} obj2.username='wade'; console.log(obj);//{username: "wade"} let arr=[1,3,{username:'kobe'}] //let testArr=[2,4] let arr2=arr.concat(); console.log(arr2); arr2[2].username='wade'; console.log(arr); let arr3=arr.slice(); arr3[2].username='anverson'; console.log(arr) console.log('--------'); let arr4=JSON.parse(JSON.stringify(arr)); console.log(arr4); arr4[2].username='duncan'; console.log(arr,arr4); */ /* * 思考: * 如何实现深度拷贝(克隆) * 拷贝的数据里面由对象/数组 * 拷贝的数据里不能有对象/数组 * 即使有对象/数组可以继续遍历对象、数组拿到里边每一项值,一直到拿到是基本数据类型, * 然后再去复制,就是深度拷贝 * */ /* * 如何判断数据类型:arr--->Array null-->Null * 1.typeof返回的数据类型:String,Number,Boolean,Undefined,Object,Function * 2.Object.prototype.toString.call() * */ let result='abcd'; result=null; // result=[1,2]; //console.log(Object.prototype.toString.call(result).slice(8,-1)) //for in 循环 对象(属性名) 数组(下标) let obj={username:'kobe',age:39}; for(let i in obj){ console.log(i) } let arr=[1,3,'abc'] for(let i in arr){ console.log(i) } //定义检测数据类型的功能函数 function checkedType(target){ return Object.prototype.toString.call(target).slice(8,-1) } //实现深度克隆-->对象/数组 function clone(target){ //判断拷贝的数据类型 //初始化变量result 成为最终克隆的数据 let result,targetType=checkedType(target); if (targetType==='Object'){ result={}; }else if(targetType==='Array'){ result=[]; }else{ return target; } //遍历目标数据 for(let i in target){ //获取遍历数据结构的每一项值; let value=target[i]; //判断目标结构里的每一项值是否存在对象/数组 if(checkedType(value)==='Object'||checkedType(value)==='Array'){//对象/数组里嵌套了对象/数组 //继续遍历获取到的value值 result[i]=clone(value) }else{//获取到的value值是基本的数据类型或者是函数 result[i]=value ; } } return result; } let arr3=[1,2,{username:'kobe'}] let arr4=clone(arr3); console.log(arr4); arr4[2].username='wade'; console.log(arr3,arr4); let obj3={username:'kobe',age:39}; let obj4=clone(obj3); console.log(obj4) obj4.username='wade'; console.log(arr4,arr3) </script>
21.set和map对象
<!-- 1. Set容器 : 无序不可重复的多个value的集合体 * Set() * Set(array) * add(value) * delete(value) * has(value) * clear() * size 2. Map容器 : 无序的 key不重复的多个key-value的集合体 * Map() * Map(array) * set(key, value)//添加 * get(key) * delete(key) * has(key) * clear() * size --> <script> /* let set=new Set([1,2,3,4,3,2,5,3,6]); console.log(set) set.add(7) console.log(set.size,set) console.log(set.has(8))//false console.log(set.has(7))//true */ let map=new Map([['aaa','username1'],[39,'age']]); console.log(map) map.set(77,'hahah') console.log(map) </script>
22.for,of循环
<!-- for(let value of target){}循环遍历 1. 遍历数组 2. 遍历Set 3. 遍历Map 4. 遍历字符串 5. 遍历伪数组 --> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <script> // let set=new Set([1,2,3,5,4,6,7]); // for(let i of set){ // console.log(i) // } let arr=[1,2,3,2,4,5,3]; let arr1=arr; arr=[]; let set=new Set(arr1) for(let i of set){ arr.push(i) } console.log(arr) </script>
23.遍历伪数组
<!-- 1. 指数运算符(幂): ** 2. Array.prototype.includes(value) : 判断数组中是否包含指定value --> <script> console.log(3**3) let arr=[1,3,4,'abc']; //console.log(arr.includes('a')); console.log(Array.prototype.includes('a')) </script>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现