JS基础:知识点

JS基础

闭包

(1)什么是闭包

能读取其他函数内部变量的函数。子级一级一级向上查找,父级不能获取子级。

(2)闭包使用场景

函数柯里化、防止变量被污染。

(3)使用不当闭包会造成什么问题?

使用不当会造面内在内泄;内泄:访问不到的变量,占用内存;

注)这个谣言来源于:IE中有bug,IE 中使用完闭包,回收不了闭包里面引用的变量

(4)总结

(1)比普通函数占用内存多。
(2)闭包不使用时,要及时释放。
(3)将引用内层函数对象的变量赋值为null。

(5)JS的垃圾回收机制?

没有用到的对象/变量。
无法访问的对象(几个对象形成一个环,互相引用)

(6)如何主动触发JS垃圾回收机制

执把这个值设置为 null

(7)垃圾回收方法【2种】

标记清除、引用计数

防抖和节流

(1)原理

防抖:输入完一段时间在调用【注册手机号/邮箱、表单点击】
节流:规定的时间内只执行一次【搜索列表、页面滚动、商品橱窗】

(2)创建表单demo

例:创建表单提交按钮,多次点击,希望只能点击一次,有什么解决方法?
(1)setTimeout 通常用这种方法(如果遇到多个的话,封装一个方法)
(2)【一刀切】一个按钮在请求 其他接口都不可再请(定义一个loading,初始 false. 请求之前改成true 请求完或是失败 false)
(3)vue自定义指令

proto 和 prototype 的区别

proto 是每个实例都有的属性;prototype 是构造函数才有的。
实例中的 proto 和构造函数的 prototype 指的是一个对象。
*number 有原型链。

注)proto 可以访问 prototype 上的属性。

(1) call、apply、bind 三者有什么区别?

【三者都可改变this 指向】
1、语法:

call(对象[,参数1,参数2,....])    //此地参数是指的是对象的参数,非方法的参数

 apply(对象, 参数数组)     // 参数数组形式: [参数1, 参数2, .....]

(2) 共同点:

(1)这三者都可以改变this指向。
(2)功能基本相同,都是实现继承/转换指针对象。与面象对象 extend 功能相似。

(3) 不同点:

(1)call 可以传多个参数,第二个参数和后面的参数可以是任意类型的数据。
(2)apply 最多支持两个参数,且第二个参数必须是数组。
(3)bind 参数和 call 相同,不会调用函数。bind 不会立马执行,会返回执行上下文被改变的函数。
(4)call 和 apply 的第一个参数都是 this 指向,直接执行。bind 是将某个函数绑定到对象上。

拷贝有哪几种方法?

(1)JSON.parse(JSON.stringify()) 【不能拷贝原型的方法,拷贝时间/正则会有问题】
(2)递归 :【达到 1000+,递归会爆】
(3)Object.assign: 【只适用于一层的对象】,可以使用Object.assign({},obj)
(4)JQ中的 extend
(5)lodash 中的 cloneDeep
(6)concat 方法:【连接两个或多个数组,不改变现有数组,得到连接数组的副本】
(7)ES6 的扩展运算符: 可以使用 […xxx]
注)vue的data 是浅拷贝,data 解决了独立性和复用性,调用一次就会有一个内存地址,和其他互不影响。

浅拷贝和深拷贝有什么区别?适用于什么场景?具体函数怎么写?

浅拷贝:复制引用数据类型的地址,如果改变内存中某个值,会影响另一个对象。【浅拷贝是拷贝的索引】
深拷贝:复制引用类型数据,如果改变其中一个值,不会影响另一个对象。【深拷贝的是数据】

注)es6 新增的方法都是深拷贝。当你使用某个对象的值,不想改变原对象,可以用深拷贝弄一个新的内存对象。

JSON.parse(JSON.stringify()) 深拷贝存在什么问题?

不能拷贝原型的方法,拷贝时间/正则也会有问题。
注)简单说就是能拷贝 array、string、number、boolean 这些扁平化的数据,JSON直接表示的。
递归进入死循环怎么解决?
通过边界值判断。

浏览器的回流与重绘

回流:页面结构发生变化时,会触发回流

页面一开始渲染
浏览器窗口大小变化
元素位置发生变化
元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
内容发生变化(比如文本变化或图片被另一个不同尺寸的图片所替代)

重绘:不改变页面结构,只改变元素的外观、风格;比如背景颜色等。

颜色修改
文本方向修改
阴影修改

注)回流一定会触发重绘,回流比重绘更消耗性能;
优化方法:修改元素时,尽量不修改原有样式,通过class 增加

浏览器的原理是什么?

(1)浏览器输入地址
(2)DNS解析
(3)TCP协议
(4)http发送请求
(5)服务器处理返回处理结果
(6)浏览器显示

浏览器为什么会跨域?【同源策略】

前后端分离的时候,前后端域名不一样,就会发生跨域问题。因为在请求中我们一般都是get/post请求。
注)同源策略:端口、协议、主机号 相同是就是同源。

跨域怎么解决?【6种】

(1)请求时头部加:header(‘Access-Control-Allow-Origin:*’)
(2)JSONP
(3)postMessage
(4)nginx 转发
(5)websocket
(6)本地 web 服务/cdn

JSON 和 JSONP 有什么区别?

JSON:返回的字符串。
JSONP:返回的脚本代码(包括函数)

(1)区别

JSON 是获取理想的数据,不能通过跨域请求;于是就把json 放在一个合法的语种中作为JS文件传过去。
json 是想要的东西;jsonp 是为了达到目的普遍采有的方法,最终也是json。
json 是目的;jsonp 是手段。json 总会用到,jsonp 跨域才会用到。

JSONP的原理?

通过 script 标签实现跨域请求。里面有src ,这个不受同源策略影响,哪都能访问。

es5的继承 和 es6的继承实现方法?以及不同点?

(1)首先要知道 JS 继承【4种】:原型继承、实继承、构造函数继承、拷贝继承。
(2)es5 主要是通过 property 或 构造函数 。

【es5 继承实质上是先创建子类的实例对象,然后将父级实例对象添加到 this 上】

(3)es6 通过 class 关键字,里面有构造函数,类之间通过 extends 关键字实现继承。

【与es5 继承机制完全不同。实质上是 先创建父类实例对象 this (必须先调用super 方法),然后用子类构造函数修改this】

基本类型和引用类型的区别?

(1)基本类型【number、boolean、string、null、undefined、symbol】
按值访问,可以对值进行操作。
(2)引用类型【object(array、function 等)】
注)简单来说通过 typeof 判断类型,如何值是 object/function 就是 引用类型。
typeof 返回的类型:string、boolean、undefined、object、function、number

typeof null  // object
typeof object // function
typeof {
    
    } // object
typeof [] // object

JS 内置对象有哪些?

基本对象:object、boolean、symbol、function。
错误对象:error、
数字和日期对象:Date、bigInt、Number、Math。
字符串:正则(RegExp)、String

【详情请看链接:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects】

ajax 请求有几个方法?get 和 post 有什么区别?

请求方法【4个】:get、post、put、delete。也有 HEAD、TRACE、CONNECT、OPTIONS方法。
get:使用url 或者 cookie 传参,速度快,有大小限制,不安全;一般创建用。
post:装数据放在body中,无大小限制,速度慢,安全;一般删除/修改用。
直面理解:本质上一样,区别在于在浏览器限制不一样

注)百度搜索用的是 get 请求,为了方便用户。

JQ 中 click 和 on 的区别?

静态资源使用时没区别。动态时只有 on 能生效;

宏任务和微任务【另一种问法就是:事件轮洵】

(1)执行顺序:先同步后异步、先微任务再宏任务。
(2)任务队列中:外层任务-------微任务------宏任务
(3)宏任务:当时调用栈中执行的任务
【主代码块、setTimeout、setInterval、setImmediate、requestAnimationFrame】
(4)微任务:当前(此次事件循环中)宏任务执行完成,下一个宏任务开始之前需要执行的任务就是微任务
【promise.then、process.nextTick、MutationObserver、catch、finally】

注)宏任务的事件放在callback queue中,由事件触发线程维护;微任务的事件放在微任务队列中,由js引擎线程维护。

setTimeout、promise、async 有什么区别?

async 是基于 promise 实现的。promise 是 ES6。async 是 ES7。
1、setTimeout 是宏任务,回调函数放在宏任务队列中,等执行栈清空后执行。
2、promise 是微任务,回调函数放在宏任务中的微任务中,等宏任务中的同步代码执行完后在执行。
3、async 表示后面有异步操作,await 后面跟的是表达式。async 方法执行时,遇到 await 会立刻执行表达式,然后把表达式的代码放到i微任务中,让出执行栈让让同步代码先执行。

注)这个问题主要考查的是三者在循环中的区别,事件循环【2种】:宏任务、微任务。

promise 什么情况下会用到?有哪些方法?分别怎么使用?

(1)理解

没出现promise 的时候,都是嵌套使用。promise 出现简单来说是为了:回调解决异步的问题。

(2)promise 的方法

(1)promise.then()如果不出错,依次执行.then 方法。
(2)promise.all()可以并行执行多个操作,在一个回调中处理返回的数据。
(3)promise.catch().then 出错的时候走catch,有自己的 err 就会走自己的error 方法。
(4)promise.finally()不管状态如何,执行完then 和 catch 后都会执行 finally 方法。
(5)promise.race () 将多个promise 实例包装成一个。
(6)promise.resove() 将现有对象转成 promise 对象。
(7)promise.reject()

(3)应用场景

(1)图片加载的时候使用 promise 。
(2)all()实现多个请求合并在一起,汇总请求结果,只需要设置一个 loading。
(3)race ()设置图片请求超时。

注)用同步的方式写异步代码。promise 中只有三种状态:进行中、成功、失败。
使用promise 时,如果后面是 同步任务,直接 return,如果后面是异步任务,需要return 一个新的 promise 方法。

(4)promise.all ()出错的时候怎么解决?

1、如果有七八个接口处理【2种方法】:使用 promise.all 或者 async/await。
2、使用 promise.all()会出现其中一个任务失败就会走 catch,怎么解决?【2种方法】
(1)改为串行
(2)promise 捕获到 error 的时候,吃掉异常,改成 resolve,约定特殊格式表示调用成功

for循环分别采用var 和 let?

for 是同步任务;setTimeout 是 异步任务
(1)进行异步任务时for循环已经循环完毕,所以得到的值 i 是循环完成之后的同一个变量 i = 5;
(2)let具有块级作用域,每次循环时,块级作用域中的 i 都是独立存在的,而 js 引擎底层又对每次迭代的 i 的值进行了记忆,所以最后打印结果为 0 1 2 3 4;

for(var i = 0;i < 5; i++) {
    
    
    setTimeout(() => {
    
    
        console.log(i)    
    })
}
// var ->输出5次 5
// let -> 0,1,2,3,

js报错堆栈溢出?有啥办法定位到是哪段代码?

溢出就是死循环了,积累变量过多不释放,肯定会溢出的。
定位:只能排查代码看有没有递归方法;或者往里面存东西;或者元素移除了,绑定的事件没有移除掉。

前端如何渲染上万条数据?【主要问的点可能还是 setTimeout 】

1、document.createDocumentFragment( ) 用来创建一个虚拟节点,节点对象不属于文档树。
2、当需要添加多个 dom 的时候,可双先把 dom 添加到虚拟节点中,最后把虚拟节点添加到页面中,这样可以减少dom 操作次数。
3、JS 是单线程的,利用 setTimeout 和 setInterval 两个函数和多线程差不多

事件委托、事件冒泡、事件捕获

事件委托:自己不想做的事情让父级去做(利用事件冒泡原理,把事件加上父级身上)
事件冒泡:自上而下触发件 (阻止事件冒泡:event.stopPropagation())
事件捕获:通过document 获取事件节点,自上而下触发

注)DOM中有两个流:事件冒泡和事件捕获

缓存

(1)cookie(同源是 4KB;支持所有浏览器;一般登录的时候用到)
(2)localStorage(同源 5MB;不手动清除,会一直在浏览器中)
(3)sessionStorage(同源5MB;浏览器窗口关闭数据丢失)

用途【2】:高性能、高并发。

new操作符具体干了什么

1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this

this 指向分别是什么?

1)箭头函数中:指的上下文this,且不能改变。
(2)普通函数/定时器:指的 window。
(3)构造函数:指的是实例对象(new 会改变 this 指向)
(4)通过事件绑定的 this: 指的是绑定的这个 this5)对象中:该方法所性的对象
(6)在函数中:this 是隐式参数。
(7)函数外,浏览器中:this是全局对象。
(8)node.js 中:this 指的是 模块 import,导出 export。
(9)传递到evel 中:直接掉用this 指的 当前对象;间接掉用 this 指的是全局对象。

window 和 document 有什么区别?

1、window 是窗体;document 是页面。
2、document 是 window 的一个子对象。
3、document.localtion 可以改变当前页面的内容;window.location 可以用其他文档更换当前的。
4、window.location 是对象,document.localtion 不是对象。

JS 怎么捕获异常?

try{
    
    
// 运行代码
}catch {
    
    
// 错误运行
}

函数申明

函数声明 大于 变量申明
函数提升 规则 函数字面量式 == 变量申明
代码块内:函数申明会提升到作用域最上面,但是函数申明 大于 变量申明

ES6

es6 的新特性有哪些?

(1)let 和 const
(2)字符串模版【${abc}
(3)箭头函数
(4)promise
(5)解构
(6)import 和 export
(7)class 定义和继承
(8)对象扩展、函数扩展
(9)proxy
(10)map、set集合去重、for of
(11)扩展运算符【…obj】

箭头函数和普通函数有什么区别?

箭头函数是 es6 的新特性,是匿名函数,不可以使用new 创建,没有原型。

var、let 和 const 有什么区别?

var 的申明挂在 window 上,可以变量名提升。
let 是变量。
const 是常量,不能为空,一旦申明必需赋值;如果申明的是复合对象,可以修改其属性。

注)let 和 const 会形成块作用域,一旦申明不能重复

字符串扩展

1.检索字符串:

(1).includes(),语法格式为:A.includes(B,index),判断A是否包含B,index表示检索的位置,从第index位置开始检索
(2).startsWith(), 语法格式为:A.includes(B,index),判断A是否以B开头,index表示检索的位置,从第index位置开始检索
(3).endsWith(), 语法格式为:A.endsWith(B,index),判断A是否以B结尾,index表示对前index个字符进行检索,这三个语句的index都是可以省略的,省略则表示检索整个字符串。

2.重复字符串:

(1).语法格式为str.repeat(n);
(2).repeat()并不会改变原来的字符串,因此需要一个变量用来接收重复后的结果,

3.去除空白

(1).trim(),语法格式为str.trim(),用于去除字符串首尾的空格
(2).trimStart(),语法格式为str.trimStart(),用于去除字符串开始处的空格
(3).trimEnd(),语法格式为str.trimEnd(),用于去除字符串结尾处的空格

TS 和 es6 有什么区别?

TS的两种类型:内部、外部;作用域【3个】全局、局部、类作用域。
es6的两种类型:导入、导出;作用域【2个】全局、局部。

优化&使用

git 版本怎么控制?

撤回commit 操作:git reset --soft HEAD^
回退版本:git reset HEAD~
回退指定版本:git reset --hard id
修改 commit 描述:git reset --amend
git config --gobal --list

(1)流程

git stash (修改的文件放到缓存中)
git pull (拉取远程代码)
git stash pop (把放在缓存中的文件放出来)
git add . (添加要提交的文件)
git commit -m ‘’ (提交的文字描述)
git push orign 分支号 (提交到某个分支)

(2)常用

git fetch origin (拉取更新远程分支)
git config user.name ‘xxx’ (提交时显示的名字)
git config user.email ‘xxx’ (提交时显示的邮箱)
git clone xxx (克隆)
git checkout xxx (切换项目分支)
git checkout -b 分支 (创建一个分支并且停留在当前分支上)
git branch(拉取分支)
git branch -r (拉取远程分支)
git branch -r (当前本地有的分支)
git log (查看日志)

代码优化

(1)少用全局变量
(2)用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
(3)用setTimeout来避免页面失去响应
(4)缓存DOM节点查找的结果
(5)避免使用CSS Expression
(6)避免全局查询
(7)避免使用with(with会创建自己的作用域,会增加作用域链长度)
(8)多个变量声明合并
(9)避免图片和iFrame等的空Src。空Src会重新加载当前页面,影响速度和效率
(10)尽量避免写在HTML标签中写Style属性

常用的状态码有哪些?分别代表什么?

2xx:接口被正常处理
200:请求成功
204:请求成功,没有资源
3xx:浏览器需要特殊处理
301:永久定向,url资源位置换了,
302:临时定向,url临时换在别的位置
303:资源更新,必须用 GET 方法
304:资源找到,但是没有符合条件的
307:和 302 差不多
4xx:服务器无法请求
400:错误请求,服务器不能理解
401:需要 http 认证
403:禁止,服务器禁止请求
404:页面没找到
5xx:服务器处理出错
500:服务器内部错误
501:尚未实施
502:错误网关
503:服务器不能用(超载/停机)
504:网关超时
505:http版本不支持

JS 新特性

参考:【https://blog.csdn.net/weixin_46719229/article/details/122313154】

JS变量前面+是什么意思?【例:+value】

可以理解成 Number(value)

可选链操作符(?.)

允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效

参考链接: https://blog.csdn.net/weixin_38551805/article/details/116199959

const dog = {
    
    
    prop: {
    
    
        name: '小七',
        ege: ''
    }
}
dog?.prop?.name // '小七'
dog?.prop?.ege // ''

空值合并操作符(??)

只有当左侧为null和undefined时,才会返回右侧的数 空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

null ?? 20  // 20
undefined ?? 3 // 3
'' ?? 3 // ''
0 ?? 4 // 0

数组

JS有几种数据类【8种】

string、number、null、boolean、object、undefined、symbol、bigInt

注)symbol 是es6新增,这种类型对象永不相等,创建时传入相同的值,解决属性名冲突,做为标记。
bigint 是 chrome 67中出现的。

NaN 是什么?

非数值型,Number 中的一种特殊类型。

null 存在的原因是什么?怎么解决?

null 存在的原因是为空对象,不存在。
做判断的时候,把 null 判断放在最前面。

Js中 == 和 === 有什么区别?

== 值相等;=== 值和类型都相等。

判断是不是数组的方法【4】

(1)Array.isArray()

(2)constructor

(3)instanceof

(4)Object.prototype.toString.call(要判断的) === ‘[object Array]’

some 和 every 的返回值?

返回true 和 flase。some 一个满足就是,every 是所有满足。

常用于:购物车全选多选。

改变原数组

【push、pop、shift、unshift、splice、reverse、sort、forEach】

不改变原数组

【map、filter、reduce、join、slice、concat、some、every】

遍历数组

【map、filter、reduce、every、some、forEach】

typeof [“男裤”, “女裤”] 为啥是object 不是数组?

数组本身也是对象,判断是否是数组不能用typeof ,应该用Array.isArrray()或者 arr instanceof Arrray。这个问题问的点是基本数据类型。

map 和 forEach 有什么区别?

map不改变原数据,forEach 改变原数组。

注)创建新数组用map;不需要制作新数组,只需要改变的时候用forEach。

map、filter、forEach、some、every 能不能跳出当前循环?

map、filter、forEach 不能,用 break 也不行。
some 可以,return false
every 可以跳出当前循环: return activityrules

JS向上取整、向下取整、四舍五入、 m 的 n 次方?

【想问的点是JS内置对象】

1)向上取整:Math.ceil(5.123) // 6 2)向下取整:Math.floor(5.123) // 53)四舍五入:Math.round(5.432) // 54)绝对值:Math.abs(-1)  // 15)取最大值:Math.max(1,2,3)  // 36)取最小值:Math.min(1,2,3) // 17)随机数:Math.random()8)m的n 次方:Math.pow(2,4) // 16 (2的4次方)
(9)保留小数:parseFloat(3.44)  // 3.44
(10)保留整数:parseInt(3.44)  // 3

数组常用的方法

1)字符串转数组:split
(2)数组转字符串:join
(3)substring: 提取字符串,日期第几位到第几位
(4)indexOf: 第一次出现的索引位置
(5)lastIndexOf: 最后一次出现的索引位置
(6)push: 在数组后面添加一个值,返回新的长度。
(7)pop:  删除最后一个值,返回删除的值。
(8)shift:  删除第一个值,返回删除的值。
(9)unshift: 在数组前面添加一个值,返回新的长度。
(10)reverse: 从大到小排序。
(11)sort: 从小到大排序。
(22)splice :从数组中获取添加/删除对象,返回被删除的元素。
(23)slice :选回返定的元素。
(24)concat : 连接两个或多个数组,返回新的数组,不改变原数组

对象数组合并【concat、遍历+、apply】

1)concat 方法【不改改原数组】
    var a=[1,2,3],b=[4,5,6];
    var c=a.concat(b);
    console.log(c) // 1,2,3,4,5,62)map遍历
    var arr1=[1,2,3],arr2=[4,5,6];
    arr2.map(item =>{
    
    
        arr1.push(item)
    })
    console.log(arr1) // 1,2,3,4,5,63)apply
    var a=[1,2,3],b=[4,5,6];
    a.push.apply(a,b)
    console.log(a)  // 1,2,3,4,5,6

对象合并【$extend、遍历+for in、Object.assign】

1)$extend
    var a= {
    
    'a': 1}, b= {
    
    'b': 1};
    $.extend(a,b)
    console.log(a)2)遍历 + for in
    let a = {
    
    a: 1},b = {
    
    b: 2, c: 3, d: 4}
    for(let i in b){
    
    
        // hasOwnProperty是判断自有属性
        // for in 循环遍历对象属性时,原型链上所有属性都将被访问,会避免原型对象扩展带来的干扰
     	if(b.hasOwnProperty(i) === true) {
    
     
          a[i] = b[i]
        }
    }
    console.log(a) // { a: 1, b: 2, c: 3, d: 4 }3)Object.assign 
    let a = {
    
    a: 1},b = {
    
    b: 2},c = {
    
    c: 3},d = {
    
    d: 4};
    let arr = Object.assign(a,b,c,d)
    console.log(a) // { a: 1, b: 2, c: 3, d: 4 }
    console.log(arr) // { a: 1, b: 2, c: 3, d: 4 }

统计数组元素出现的次数

let demo = ['aa','bb','cc','aa','1','cc','cc','bb']
let obj = {
    
    }
demo.map(item =>{
    
    
    if(obj[item]){
    
    
        obj[item]=obj[item]+1;
    } else {
    
    
        obj[item] = 1
    }
})
console.log(obj) // {1: 1, aa: 2, bb: 2, cc: 3}

for of 和 for in 有什么区别?for of 怎么能使对象遍历?

(1)区别:代码如下

for in 遍历获取的是对象的 key ,也就是索引值。
for of 遍历获取的是对象的 value,也就是对象的值。

var arr = ['red', 'green', 'blue']1for in 遍历获取的是对象的 key,就是索引值
    for(let item in arr) {
    
    
      console.log('结果', item)
    }
    > "结果" "0"
    > "结果" "1"
    > "结果" "2"2for of 遍历获取的是对象的 关键字,就是值        
    for(let item of arr) {
    
    
      console.log('结果', item)
    }
    > "结果" "red"
    > "结果" "green"
    > "结果" "blue"3for of 怎么能使对象遍历

数组去重有哪几种方法?【12种】数组去重和对象去重有什么区别?

(1)filter
(2)reduce + includes
(3)includes (判断是否有这个值)
(4)indexOf (通过 indexOf === -1 判断)
(5)for 嵌套,里面splice 去重
(6)sort 排序,和相邻元素对比
(7)[…new Set(arr)]
(8)set 去重
(9)递归去重

方法8:Array.from(new Set(arr))

方法34:includes、indexOf
function unique(arr) {
    
    
    // 先判断是不是数组
    if (!Array.isArray(arr)) {
    
    
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
    
    
        // indexOf 方法
        if (array.indexOf(arr[i]) === -1) {
    
    
            array.push(arr[i])
         }
        // includes 方法
        if(!array.includes(arr[i])) {
    
    
          array.push(arr[i])
        }
    }
    return array;
}
方法5for 嵌套,里面splice 去重
function unique(arr){
    
                
        for(var i=0; i<arr.length; i++){
    
    
            for(var j=i+1; j<arr.length; j++){
    
    
                if(arr[i]==arr[j]){
    
             //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}

//数据
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{
    
    },{
    
    }];
console.log(unique(arr))
//结果 [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]  //NaN、{}没有去重

猜你喜欢

转载自blog.csdn.net/u013592575/article/details/124736358
今日推荐