前端面试真题

1、var、let和const的区别?

  • let、const是es6的语法;var有变量提升
  • var、let是变量;const是常量,不可修改
  • let、const有块级作用域,var没有

1.1、变量提升

//变量提升
var a = 100
console.log(100)//100
console.log(b)//undefined
var b = 200

console.log(c)//报错,在输出前没有声明变量
let c = 300
======================上面代码类似于================================
var a = 100
var b
console.log(a)//100
console.log(b)//undefined
b = 200

console.log(c)//报错,在输出前没有声明变量
let c = 300

1.2、const为常量

const a = 100
a = 200 //报错:赋值给常量

1.3、块级作用域

for(var i = 0;i<10;i++){
	var j = i
}
console.log(i)//10
console.log(j)//9
===================用了letconst就会报错==================

for(let i = 0;i<10;i++){
	let j = i
}
console.log(i)//i is not defined
console.log(j)//j is not defined

2、typeof能返回那些类型?

typeof可以返回所有的值类型,如undefined、string、boolean、number、symble
typeof可以判断引用类型为object,如array,object,null
typeof可以判断函数类型为function

3、什么时候使用==什么时候使用===

除过判断null或者undefined,其他情况都用===
应为a==null相当于a===null||a===undefined

let a
a  == null //true
let b = null
b == undefined ///true

4、列举强制类型转换和隐式类型转换

详细的讲解的文章

强制:parseInt parseFloat toString
隐式:if,逻辑运算,==,+拼接字符串

//toString()方法不能直接用比如123.toString()
	let a = 123
	a.toString()//success
	123.toString()//fail
	12.3.toString()//success
	123 .toString()//success
//逻辑运算+-*/%等,当数字和字符串都出现的时候,只有符号的+的时候才会吧数字变成字符串,其他的情况都是吧字符串变成数字
//parseInt()的第一个参数是传进来的值,第二个参数是要转换成几进制,不填默认为0,认为是10进制,如果传0x或者0X则转换为16进制,这个值的范围是2-36,否则返回NaN

5、手写Lodash.isEqual()深度比较


function isObject(obj){
    if(typeof obj === 'object' && typeof obj != null){
        return true
    }
    return false
}
function isEqual(obj1,obj2){
    //判断类型
    if(!isObject(obj1) || !isObject(obj2)){
        return obj1 === obj2
    }
    //判断穿的是不是同一个
    if(obj1 === obj2)
    {
        return true
    }
    //获取object的keys放在一个数组
    const keys1 = Object.keys(obj1)
    const keys2 = Object.keys(obj2)
    if(keys1.length !== keys2.length)
    {
        return false
    }
    for(let key in obj1){
//注意这里如果获取object的每一项的内容时,因为是动态获取,所以不能用点的形式
       //递归
        let res = isEqual(obj1[key],obj2[key])
        //不一样直接返回
        if(!res){
            return false
        }
    }
    //都没问题返回true
    return true
}

5、split和join

	"1-2-3".split("-") //[1,2,3]
	[1,2,3].join("/") //"1/2/3"

6、数组的pop,shift,unshift,push分别是什么?(功能,返回值,是否会对原来的数组造成影响)

纯函数
不改变原数组,返回一个函数
concat、map、filter、slice(切片)


非纯函数
push、pop、unshift、shift、some、every、forEach、spilce(剪接)、reverse

let arr =  [1,2,3]
console.log("arr",arr)//[1,2,3]
//纯函数 1:不改变原属组(无副作用),2:返回一个数组
let arr1 = arr.concat([4,5,6])
console.log("arr1",arr1) //[1,2,3,4,5,6]
let arr2 = arr.map(res=>res*10)
console.log("arr2",arr2) //[10,20,30]
let arr3 = arr.slice(1,2)//类似进行深拷贝,不会影响原数组(开始的下标(包括),结束的下标(不包括)),返回切下的部分
//slice传一个就从这个开始到数组结束,slice传负数就是从后往前截取,slice不传就是拷贝这个数组(不是复制地址)
console.log("arr3",arr3) //[2]
let arr4 = arr.filter(res=>res<2)
console.log("arr4",arr4) //[1]
// 非纯函数
let arr5 = arr.push(4)//向数组尾部添加一个元素
console.log("arr5",arr5) //4 返回数组的长度
console.log("arr",arr)//[1,2,3,4]
let arr5 = arr.pop(6)//删除数组尾部的一个元素
console.log("arr5",arr5) //3 返回删掉的元素
console.log("arr",arr)//[1,2]
let arr5 = arr.unshift(6)//向数组头部添加一个元素
console.log("arr5",arr5) //4
console.log("arr",arr)//[6,1,2,3]
let arr5 = arr.shift(6)//删除数组头部第一个元素
console.log("arr5",arr5) //1
console.log("arr",arr)//[2,3]
//判读是不是有一个数字大于2
const a = arr.some(function(item,index,arr){
    return item > 2
})
console.log(a)//true
//判断是不是所有数字都大于2
const b = arr.every(function(item,index,arr){
    return item > 1
})
console.log(b)//false
//遍历这个数组
arr.forEach((item,index)=>{
    console.log(item,index)
})
//剪届一个数组(第一个参数是开始的下标,第二个参数是减去的长度,后面的都是参数)
arr.spilce(1, 2, 'a', 'b', 'c')//返回切下的部分[2,3]
//反转数组
arr.reverse()//返回被翻转后的函数[3,2,1]

注意:这里补充一个方法reduce方法,他虽然不会改变原数组,但是这里因为他返回的是一个我们定义的东西,所以无法界定,reduce被我们常用于统计数组中的一个数据

//let 结果 = 数组.reduct(累加器, 初始化值)
//累加器
//(累加结果, 当前值, 当前索引, 整个数组)=>{

	//return 处理结果
//}
let a = [1, 2, 3, 4]
a.reduce((count, current, index, arr) => 
{ 
	return count + (current > 2 ? 1 : 0) 
}, 0)//求数组中大于2的数有几个 2

7、[10, 20, 30].map(parseInt)的结果

//上面是简写形式,展开是这样
[10,20,30].map((item,index)=>{
	parseInt(item,index)
})//[10,NaN,NaN]
//第一次parseInt(10,0)>10
//第二次parseInt(20,1)>NaN
//第三次parseInt(30,2)>NaN

8、ajax的get和post请求的区别

get请求一般获取数据,post一般上传数据
get传的参数拼接在url里面,post传的参数在请求体里面(体积大)
post安全性好点,

9、call和apply的区别

apply的第二个参数是一个数组,call和bind的传参是一个一个传
bind改变this指向以后不会立即执行,而call和apply会立即执行

10、事件代理(委托)

写一个函数利用事件冒泡管理事件
事件代理/事件委托详情

11、闭包会产生的问题

闭包相关

闭包会产生的问题,变量不能被释放

//闭包会产生的问题,变量不能被释放
function a(fn){
	let num = 100;
	fn() 
}
let num = 200//!!!这里的变量被作为参数传给a所以不能被释放
function b(){
	console.log(num)
}
a(b)//200
function c(){
	let f = 300//!!!这里的300被作为返回的函数里面的参数,所以不能被释放
	return function(){
		console.log(f)
	}
}
let d = c()
let f = 800
d()//300

12、阻止默认事件和阻止冒泡

描述的比较详细的介绍

  • 冒泡是从子元素往外,捕获是从父元素往内,如果两个都存在,先捕获后冒泡
  • api:ele.preventDefault() | 阻止默认事件;ele.stopPropagation() | 阻止冒泡
  • addEventListener(‘事件’,ele=>{console.log(ele)},false);第三个参数默认是false,意思是先执行冒泡,如果为true就是先捕获再冒泡
<div class="container">
    <a class="aa" href="https://baidu.com">
    </a>
</div>
<script>
    const container = document.getElementsByClassName('container')
    const aa = document.getElementsByClassName('aa')
    console.log(container)
    aa[0].addEventListener('click',res=>{
        res.preventDefault()//加了这个a就不会跳转了
        res.stopPropagation()//加了这个就不会点击a的时候div也被触发了        console.log('a')
    })
    container[0].addEventListener('click',res=>{
        console.log('div')
    })
</script>

13、DOM操作的常见api

DOM操作详细的介绍

14、如何减少DOM操作

减少DOM操作

我们为什么要减少DOM操作?因为DOM查询操作是非常耗费性能的,我们要尽可能的减少对DOM的查询,删除,移动等操作

  • 我们可以通过吧查询到的DOM保存在一个变量里,减少查询DOM次数,
  • 我们需要同时对DOM进行很多操作时,可以先创建一个DOM片段,然后对着干片段操作,等所有操作都做完了以后,在吧它插入到我们的DOM树里面

15、Jsonp,为何不是真正的ajax

jsonp原理好文章jsonp的实现原理和XMLHttpRequest请求

Jsonp是通过标签的,ajax是通过XMLHttpRequest的请求的
可以 不受同源策略限制的标签

  • script img link css标签
    -iframe可以引入外源,但是不能操作外源

script标签和link标签作为同源策略的区别

  • script标签里面是直接可以放可执行脚步,加载js文件就会执行,使用link等标签要用onload的执行这个里面的东西

16、document的load和ready的区别

onload和DOMContentLoaded和load

一个是当dom加载完毕执行,一个页面只出现一个onload;一个是当DOM加载完执行,此时的图片资源可能没加载完;一个是当DOM加载完毕,图片加载完再执行

17、=====的区别

==和===区别

==可能会进行数据类型转换;===不会类型转换,会完全比较
建议只在判断null的时候用==,其他都用===

18、函数声明和函数表达式的区别

函数声明会在代码加载之前对函数进行预处理,函数表达式的话就不会

console.log(sum(1,2))//3
function sum(a, b) {
return a + b
}
------------------------------------------------------------------
var res = sub(3,1)//sub is not a function
console.log(res)
var sub = function(a, b) {
return a - b
}

19、new Object() 和 Object.create()的区别

new Object() 是创建一个对象和直接{}一样,Object.create()是创建一个没有原型的对象,我们需要指定原型

let obj1 = {
  name: 'potkiss'
}
let obj2 = new Object({
  name: 'potkiss'
})
let obj3 = new Object(obj1)
console.log(obj1 === obj2)//false,创建了一个新的对象
console.log(obj1 === obj3)//true,因为传进来的对象是obj1,所以obj3只是吧obj1的内存地址搞过来了
//后面的方法创建的对象默认没有隐式原型,当我们传入一个对象后创建的这个对象的隐式原型会指向传入对象的显式原型
let obj4 = Object.create(null)
let obj5 = Object.create(obj1)
console.log(obj4)//{},无__proto__
console.log(obj5)//{},它的__proto__指向obj1
obj5.__proto__.name = '99'
console.log(obj1.name)//,99

20、关于this的一道面试题

这里记住一点那里执行去哪里找,所以第二个输出就会报错

const people = {
  age: 30,
  speak:function(){
    return this.age
  }
}
console.log(people.speak())//30
let a = people.speak
console.log(a())//undefined age

21、关于自由变量和作用域的题

let i
for (i = 1; i <= 3; i++) {
  setTimeout(function(){
    console.log(i)
  },0)
}
//输出了3个4
let a = 100
function b(){
  alert(a)
  a = 10
  alert(a)
}
b()
alert(a)
//先100、10、10

21、正则表达式

正则学习推荐教程

22、手写trim方法,保证浏览器兼容性

String.prototype.trim = function() {
	return this.replace(/^\s+/,'').replace(/\s+$/,'')
	//"\s"匹配字符串前面和后面的子表达式的空白字符,"+"匹配一次或多次
}

23、如何获取多个数字中的最大值

可以用Math.max()来直接得到,也可以自己手写一个通过遍历转换的数组,得倒最终的

function max() {
	const array = Array.prototype.slice.call(arguments)
	let num = 0
	array.forEach((item, index)=>{
		if(item>num) {
		num = item
		}
	})
	return num
}

24、用js实现继承

super 和 extends
js实现继承文章

25、如何捕获js的异常

  1. 手动捕获:可以使用try和catch来捕获异常
  2. 自动捕获:可以使用window.onerror = function( message, source, rowNum, colNum, error) {
    // 对于跨域的js,如CDN的资源,不能捕获
    // 对于压缩的js,需要配合sourceMap来定位行和列
    }

26、什么是JSON格式

  1. JSON数据格式本身是一种字符串,结构类似于JS中的对象,所以对JS更友好
  2. window.JSON是一个全局的对象,JSON.parse()是吧js格式的字符串变成JSON格式,JSON.stringify()是吧JSON格式的数据变成字符串

27、怎样获取url上的参数的值

这里展示了两种办法,一个用api一个用正则

// 兼容性好的方法 使用正则
function locationSearch(name){
	// a=9&b=99
	const loca = location.search.substring(1)
	// 开始或者以&开始,name = 除了&符号都可以 以&或者结束结尾
	const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`,'i')// 这里的i是大小写不区分
	const res = loca.match(reg)
	if(res == null) {
		return
	}
	return loca.match(reg)[2]
}
console.log(locationSearch('b'))
// 简单,但是兼容性不好,使用新的api
function getSearch(date) {
	const loca = location.search
	const parem = new URLSearchParams(loca)
	console.log(parem.get(date))
}
getSearch('a')

28、解析url为一个对象

第一种方法是普通的location方法然后字符串解析,第二种是用新的API来解析URL

// 1.解析url为一个对象
// 普通方法
let obj = {}
const loca = location.search.substring(1)
loca.split('&').forEach(item=>{
	const par = item.split('=')
	obj[par[0]] = par[1]
})
console.log(obj)
// es6的API方法
let obj2 = {}
const loca2 = location.search.substring(1)
let parem = new URLSearchParams(loca2)
parem.forEach((value,name) => {
	obj2[name] = value
})
console.log(obj2)

29、手写一个flatern函数,拍平数组

两层的数组直接用Array的原型上的concat方法+apply就可以完成,多层需要递归

// 2.手写一个flatern,考虑多层级
let arr1 = [1,2,3,4,5]
let arr2 = [1,2,3,[4,5]]
let arr3 = [1,2,3,[4,[5]]]
let arr4 = [1,2,3,[4,[5,[6,7]]]]
const flatern1 = [].concat.apply([],arr2)// 这个只能两个层级的拍平
console.log(flatern1)
function flatern2 (arr) {
	// 判断数组中有没有某一项是数组
	const needFlatern = arr.some(item=>{return item instanceof Array})
	if(!needFlatern) {
		return arr
	}
	 let tempArray = [].concat.apply([],arr)
	 return flatern2(tempArray)
}
console.log(flatern2(arr4))

30、数组去重

一种方法是遍历比较,一种方法是用集合的数据唯一性

// 3.数组去重
// 普通方法
function moveRepeat(arr) {
	const res = []
	arr.forEach(item=>{
		if(res.indexOf(item) == -1) {
			res.push(item)
		}
	})
	return res
}
console.log(moveRepeat([1,2,3,3,2,3,1,5]))
// 利用集合的每一项都是唯一的性质
function moveRepeat2(arr) {
	const res = new Set(arr)
	return [...res]
}
console.log(moveRepeat2([1,2,3,3,2,3,1,5]))

31、手写深拷贝

function deepClone(obj) {
	if (typeof obj !== 'object' || obj == null) {
		return obj
	}
	let res
	if (obj instanceof Array) {
		res = [] 
	} else {
		res = {}
	}
	for (let key in obj) {
	//判断是不是自己的别是别人的
		if (obj.hasOwnProperty(key)) {
		//递归
			res[key] = deepClone(obj[key])
		}
	}
	return res
}
let person = {
	name: 'potkiss',
	school: {
		name: 'xxx',
		teacher: 'kisspot'
	},
	age: 90
}
let clonePerson = deepClone(person)
clonePerson.age = 80
console.log('person',person) //age=90
console.log('clonePerson',clonePerson) //age=80

要注意Object.assign()不会深拷贝,是浅拷贝

let person1 = {
	name: 'potkiss',
	school: {
		name: 'xxx',
		teacher: 'kisspot'
	},
	age: 90
}
let person2 = Object.assign({}, person1, {height:190})
person1.age = 30
console.log(person1) //age=30
console.log(person2) //age=90
// 这里我们发现的确不是简单的拷贝了内存地址,但是,当这个对象再深的时候,就不好使了
person1.school.teacher = 'kkk'
console.log(person1) //person1.school.teacher=kk
console.log(person2) //person1.school.teacher=kk

32、介绍RAF-requestAnimationFrame

  • 当我们用js写动画的时候,如果用setTimeout的话,我们切换到后台标签或者iframe里面,定时器还会继续执行;再一个,要实现帧率稳定,需要我们根据帧率自己配置时间,比较麻烦。
  • 我们用RAF的话浏览器会自动帮我门计算完成的时间,而且,当我们切换标签等操作,定时器会暂停,我们切回来的时候,动画会继续之前的继续变化,优化了浏览器的性能。

33、性能优化,从那几个方面考虑

减少DOM操作
性能优化(节流,防抖)

  • 多使用内存,缓存,减少计算,减少网路请求
  • 加载页面,页面渲染,页面流畅等,比如使用懒加载,节流,防抖等等

34、有序和无序

  • 有序是数据按照一定的顺序排,操作某一个,会影响后面其他的所有,所以操作比较慢
  • 无序是排列没有顺序,但是操作起来比有序快很多
  • js中数组是有序的,对象是无序的
  • 结合有序和无序的优点的是什么——二叉树以及其变种
// 无序的对象
let a = {
	1: 100,
	3: 300,
	2: 200
}
console.log(Object.keys(a))//[1,2,3],有序的数组

35、Map和Object的区别

35.1、Map的API操作

包括了map的修改,增加,删除,查看key,查看value,遍历,长度,迭代器,清空

const map = new Map([[3,300],[1,100],[2,200]]) 
// 修改
map.set(3, 400)
console.log(map)
// 添加
map.set(5, 500)
console.log(map) //Map(4) {3 => 400, 1 => 100, 2 => 200, 5 => 500}
// 查询
console.log(map.has(1)) // true
console.log(map.get(2)) // 200
// 删除
map.delete(1)
console.log(map) //Map(3) {3 => 400, 2 => 200, 5 => 500}
// 遍历注意第一个参数是值,第二个是key
map.forEach((value,key,map)=>{console.log(key, value,map)}) // 3 400 Map(3) {3 => 400, 2 => 200, 5 => 500}...
// 长度
console.log(map.size) // 3 注意不是一个functio
// 迭代器
let a = map.keys()
console.log(a.next().value) //3
console.log(a.next().value) //2
console.log(a.next().value) //5
let b = map.values()
console.log(b.next().value) //400 
console.log(b.next().value) //200
console.log(b.next().value) //500
let c = map.entries()
console.log(c.next().value) //(2) [3, 400]
console.log(c.next().value) //(2) [2, 200]
console.log(c.next().value) //(2) [5, 500]
// 清空map
map.clear()
console.log(map) // Map(0) {size: 0}

35.2、Map是有序的,Object是无序的

我们输出Map的typeof发现他是object,说明会速度很快;下面的代码又证明Map是有序的,所以Map同时具有数组和对象的所有优点

const map = new Map([[3,300],[1,100],[2,200]]) 
console.log(typeof map) //object
console.log(map) //Map(3) {3 => 300, 1 => 100, 2 => 200}
map.forEach((value,key)=>{console.log(key, value)}) //3 300 1 100 2 200

const obj = {3:300, 1:100, 2:200}
console.log(typeof obj) // object
console.log(obj) //{1: 100, 2: 200, 3: 300}
console.log(Object.keys(obj)) // ['1', '2', '3']

35.3、Map和Object速度的比较

在小数据的情况下,三者速度差不多,所以我们这里循环多次,由下面的实验可以得出,Map作为一个有序的数据形式的速度提升了不少,甚至有时比Object都稍微快点

//Object
let obj = {}
for(let i = 0; i < 1000*1000; i++){
	obj[i] = i
}
console.time('obj add')
obj[4] = 400
console.timeEnd('obj add') //0.010986328125 ms
console.time('obj delete')
delete obj[3]
console.timeEnd('obj delete') // 0.0029296875 ms
//Array
let arr = []
for(let i = 0; i < 1000*1000; i++){
	arr[i] = i
}
console.time('arr add')
arr.push(4)
console.timeEnd('arr add') // 0.010009765625 ms
console.time('arr delete')
arr.shift(1)
console.timeEnd('arr delete') // 0.9521484375 ms
//Map
const map = new Map() 
for(let i = 0; i < 1000*1000; i++){
	map.set(i,i)
}
console.time('map add')
map.set(5, 500)
console.timeEnd('map add') //0.0048828125 ms
console.time('map delete')
map.delete(1)
console.timeEnd('map delete') //0.005859375 ms

35.4、Map的key可以是一个函数或者对象

map 的每一项的key值可以是一个对象或者函数,但是Object的key值不能是函数或者对象

const map = new Map([[function(){},300],[{2:200},100],[2,200]]) 
console.log(map) // Map(3) {ƒ => 300, {…} => 100, 2 => 200}

这个性质我们可以用在那里呢?

  • 当我们想让两个或者多个对象关联的时候,Object的方法是让他的某一个值是另一个,这样会造成这个对象很大,这时我们可以用这个Map,让Map某一项的key为这个被指向的Object
// Object
let a = {
	age: 30
}
let b = {
	name: 'potkiss'
}
a.name = b
console.log(a) // {age: 30, name: {…}}
//Map
const map = new Map([['age', 30]]) 
map.set('name',{name: 'potkiss'})
console.log(map) // Map(2) {'age' => 30, 'name' => {…}}

36、Set和数组的区别

36.1、Set的API操作

包括了对set的查,删,加,遍历,迭代器,清空等操作

// Set 
let set = new Set([1,2,4,3])
// 增加
set.add(5)
console.log(set) // Set(5) {1, 2, 4, 3, 5}
// 删除
set.delete(1)
console.log(set) // Set(4) {2, 4, 3, 5}
// 查询
console.log(set.has(1)) // false
// 返回各种迭代器,它们是为了兼容Map而提供的
let a = set.keys()
console.log(a.next().value) // 2
console.log(a.next().value) // 4
let b = set.values()
console.log(b.next().value) // 2
console.log(b.next().value) // 4
let c = set.entries()
console.log(c.next().value) // (2) [2, 2]
console.log(c.next().value) // (2) [4, 4]
// 长度
console.log(set.size) // 4
// 遍历
set.forEach((item,key,set)=>{console.log(item,key,set)}) //2 2 Set(4) {2, 4, 3, 5}...
// 清空集合
set.clear()
console.log(set) // Set(0) {size: 0}

36.2、 Set是无序的很快,数组是有序的很慢

  • Set是无序的,数组是有序的
  • 下面的数据可以看到两者在增加、删除的速度,差距还是比较大的,可以考到Set的速度有质的飞跃
//Array
let arr = []
for(let i = 0; i < 1000*1000; i++){
	arr[i] = i
}
console.time('arr add')
arr.push(4)
console.timeEnd('arr add') //1.264892578125 ms
console.time('arr delete')
arr.shift(1)
console.timeEnd('arr delete') // 0.884033203125 ms
// Set 
let set = new Set()
for(let i = 0; i < 1000*1000; i++){
	set.add(i)
}
console.time('set add')
set.add(4)
console.timeEnd('set add') // 0.0048828125 ms
console.time('set delete')
set.delete(1)
console.timeEnd('set delete') // 0.0068359375 ms

36.3、Set的数据是唯一的,不重复

我们利用这一特性来数组去重(前面有)

let set = new Set([1,2,3,3,2,1])
console.log(set) // Set(3) {1, 2, 3}

37、WeakMap和WeakSet

37.1、可以直接看这一篇,讲解了JS的垃圾回收机制等,很详细

这俩和Map、Set的区别

  • WeakMap和WeakSet他们是弱引用类型,会防止内存泄漏
  • 因为WeakMap和WeakSet是弱引用的所以只有delete、get、set、has和add、delete、has这几个API
  • WeakMap的键值必须是对象,WeakSet的值必须是对象

37.2、他俩与Map和Set的对比

// 强引用Map
let map = new Map()
function addMapItem1() {
	const person1 = {name: 'potkiss'}
	map.set(person1, 99)
}
addMapItem1()  // 执行完后person1没有被销毁,应为map还在用
// 强引用Set
let set = new Set()
function addSetItem1() {
	const person3 = {name: 'potkiss'}
	set.add(person3)
}
addSetItem1()  // 执行完后person3没有被销毁,应为set还在用
// 弱引用WeakMap
let wMap = new WeakMap()
function addMapItem3() {
	const person2 = {name: 'potkiss'}
	wMap.set(person2, 99)
}
addMapItem3()  // 执行完后person2被销毁,应为wMap是弱引用
// 弱引用WeakSet
let wSet = new WeakSet()
function addSetItem4() {
	const person4 = {name: 'potkiss'}
	wSet.add(person4)
}
addSetItem4()  // 执行完后person4被销毁,应为wSet是弱引用

37.3、使用场景

使用场景

38、数组的reduce方法

reduce的案例分享-注意点7

  • reduce 一般使用在数组的求和,统计,字符串的拼接等条件统计的应用场景
  • reduce的参数(函数,初始值),函数的参数有4个,分别是,(初始值的求和结果,当前项,当前索引,整个数组)
let arr = [10, 20, 30, 40]
const res = arr.reduce(function(sum, current, index, array){
	return sum = sum + current
},0)
console.log(res) // 100
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值