经典面试题第六更---十月一的11道笔试题

 前言:
    🤡 作者简介:我是Morning,计算机的打工人,想要翻身做主人 🙈 🙈 🙈
    🏠 个人主页:Morning的主页
    📕系列专栏: 前端面试备战
    📞 如果小编的内容有欠缺或者有改进,请指正拙著。期待与大家的交流
    🔥如果感觉博主的文章还不错的话,👍点赞👍 + 👀关注👀 + 🤏收藏🤏

                        

文章背景: 

在9.29🌕🌕🌕那天好多同学都回了家,我下午早早的吃了晚饭回到了自习室学习。挺大的一个考研教室,只有我一个人这么早来学习。(我只是找一个安静的学习环境,其实我不考研哈哈哈)。我是坐在窗户边的位置,看着一年中最圆的月亮,还有空寂的教室,当时的思乡情节达到了巅峰👾  👾 (其实只是太孤寂了哈啊哈哈)。但是还是埋下头来好好学习,写了几道大厂笔试题。

其实大家要知道,前端水准体现在哪里?我认为不是你的Vue、React使用的有多6,而是JS的熟练程度决定了水平。一昧的只知道使用框架做需求,那不就是一个前端切图仔么。💢💢

一定一定要开始重视JS的基础兄弟们,加油👊👊👊

今天呢和大家分享一下最近学习的笔试题。既然是10月1日的国庆节,那么就来11道题吧。只有对祖国没用的人才放假,给我冲!!

如果大家也有好的学习资源希望大家评论区多多留言

目录

文章背景: 

一.翻转字符串

二.数组去重

1.Set

2.双重循环

3.indexOf/includes

4.filter 

三.找出任意html中的所有不重复的html的标签

四.手写实现数组map和filter方法

map

filter

map与filter的区别与区别

五.手写call、apply

call

apply

六.获得20~50之间的随机数

七.写一个事件委托

八.写一个函数可以返回参数的具体数据类型

九.写一个函数来计算参数的和

1.使用循环 

2.使用reduce

十.每隔1s打印当前时间,格式为YYYY-MM-DD hh:mm:ss

十一.能否使用某种方式将下面的语句使用展开运算符而不导致类型错误


一.翻转字符串

var str='sumaolin'

console.log(str.split('').reverse().join(''));//方法一
console.log([...str].reverse().join(''));//方法二
console.log(Array.from(str).reverse().join(''));//方法三
var res=[]
for(var i=str.length-1;i>=0;i--){
    res.push(str[i])
}
console.log(res.join(''));//方法四
console.log(str);//sumaolin

在这里使用了四种方式,前三种本质上是先变成数组使用数组的reverse方法,在变回字符串。最后一种是使用了循环,相比就比较复杂一些些。主要是考察大家的数组和字符串方法

此外注意这些数组或者字符串的方法并没有改变原来字符串的值

这几个数组方法会改变原数组,其余的大多不变

push、unShilft//返回值是数组的长度
pop、shilft //返回值是被删掉的值
splice //返回的是被删掉的值组成的一个数组
reverse //返回反转后的数组
sort //返回排序后的数组                 

字符串方法目前据我所知并没有改变原字符串的方法

二.数组去重

1.Set

使用Set去重之后得到的结果是一个Set类型,使用扩展运算符将其变为数组类型

function unique(arr){
    return  [...new Set(arr)]
}
console.log(unique(arr));

2.双重循环

让数组中的一个元素和前面的所有元素比较,如果相等,就把那个元素删除(因为删除了一个元素,下一个元素的下标就需要-1)。那个元素便是外层循环中的i,与之相比的就是内层循环中的j。

function unique(arr){
    for(var i = 1;i<arr.length;i++){
        for(var j = 0;j<i;j++){
            if(arr[i]===arr[j]){
                arr.splice(i,1);//删除1个从索引为i开始的元素
                i--;
            }
        }
    }
    return arr
}
console.log(unique(arr));

3.indexOf/includes

indexOf:在数组中找到参数第一次出现时的下标,不存在返回-1(其实我个人认为indexOf在字符串中的使用更多一点,不介意在数组中使用indexOf)

function unique(arr){
    var newArr=[]
    for(var i = 1;i<arr.length;i++){
    //如果在新数组中找不到在原数组中遍历的元素的话,就将其加入到新数组
        if(newArr.indexOf(arr[i])==-1){
            newArr.push(arr[i])
        }
    }
    return newArr
}
console.log(unique(arr));

includes:判断一个数组是否包含一个指定的值,如果是返回 true,否则false。

function unique(arr){
    var newArr=[]
    for(var i = 1;i<arr.length;i++){
        if(!newArr.includes(arr[i])){
            newArr.push(arr[i]) 
        }
    }
    return newArr
}
console.log(unique(arr));

4.filter 

通过filter遍历数组的每一个元素,如果该元素的下标==使用indexOf查找该元素返回的下标,则证明是第一次出现。将所有第一次出现的元素收集起来就完成了去重

function unique(arr){
    var newArr=[]
    arr.filter((item,index)=>{
        console.log(item,index);
        if(arr.indexOf(item)==index){
            newArr.push(item)
        }
    })
    return newArr
}
console.log(unique(arr));

5.reduce 

对于reduce不熟悉的小伙伴看我的此篇博客 

var names=['Alice','Ben','Cris','Dog','Elephant','Ben']
var obj=names.reduce((pre,cur)=>{
    if(!pre.includes(cur)){
        return pre.concat(cur)
    }else{
        return pre
    }
},[])
console.log(obj);//['Alice', 'Ben', 'Cris', 'Dog', 'Elephant']

三.找出任意html中的所有不重复的html的标签

😣😣😣第一次看到这个需求的时候我的表情就是这样的,不知道小伙伴写的时候是不是想我一样毫无头绪。但只用两行短短的代码就可以完成这个需求

var arr=[...document.querySelectorAll('*')].map(v=>v.tagName);
console.log([...new Set(arr)]);

<1>使用通配符查找出所有元素(此时结果是伪数组),

<2>使用扩展运算符将其变为数组

<3>使用map方法提取出标签名

<4>使用Set数组去重

console.log('这个代码也可以合并成一行')
[...new Set([...document.querySelectorAll('*')].map(v=>v.tagName))];//报错

 但是要注意❗❗❗上面可一定要加分号呀,不然js会认为你下面的代码会拼接到上一行,要养成良好的编程习惯

四.手写实现数组map和filter方法

一提到手写方法,可能很多小伙伴都感觉很难,无从下手

第一,你要熟悉这个方法,明白怎么去使用。在写之前可以使用一下,更有利于书写思路

第二,捋清楚调用者是谁,返回值是什么

第三,要清楚要在原型链上去写方法,会经常使用到this

map和filter方法,调用者都为数组,都是输出一个新数组,参数为回调函数

map

var arr=[1,2,3]
console.log(arr.map(v=>v+1));
//map方法传入的参数是个回调函数,即
function fn(v){
    return 
}
//开始手写方法
Array.prototype.Mymap=function(fn){
    var newArr=[]
    for(var i=0;i<this.length;i++){
        newArr.push(fn(this[i]))
    }
    return newArr
}
console.log(arr.Mymap(v=>v+1));

filter

var arr=[1,2,3]
console.log(arr.map(v=>v<3));
//回调函数
function fn(v){
    return v<3 //返回的是一个布尔值
}
//开始手写方法
Array.prototype.MyFilter=function(fn){
    var newArr=[]
    for(var i=0;i<this.length;i++){
        if(fn(this[i]))
        newArr.push(this[i])
    }
    return newArr
}
console.log(arr.MyFilter(v=>v<3));

map与filter的区别与区别

首先都将原数组进行了遍历,使用每一个原数组的元素传入回调进行处理

区别:

1.回调函数的不同

map返回的是处理后的值,filter返回的是是否符合条件得出的布尔值

2.传入新数组的值不同。

map传入的是处理后的值,filter传入的是回调返回结果为true的原数组的元素

五.手写call、apply

call

首先捋清楚思路,我们从运用可以看出来,

  1. getName要执行
  2. 我们想要getName的this指向man,也就是call的参数(context)
  3. 是getName调用了call函数,所以我们要写的apply方法中的this就是GetName
  4. 如果在context里面定义一个函数fn,fn又恰好是我们想要执行的getName的话,那么getName里面的this就变成了context。这个时候 bingo!🔥🔥我们想要的结果就神奇的出来了

其核心思想就是将要调用的函数放到有数据的对象中,将函数中的this指向这个对象。

var person={
    getName:function(){
        return this.name
    }
}
var man={
    name:'苏茂林'
}
//call的运用
console.log(person.getName.call(man));
//开始手写call方法
Function.prototype.myCall=function(context){
    var result
    //不确定是否传了参数,如果没传,就让他指向window
    var context=context||window;
    //getName要执行,this要指向context
    context.fn=this

    //不确定传入参数的个数,但是第一个肯定是this要指向的对象,其余的参数就是getName所需要的参数
    //将context后面的参数全拿出来。arguments返回的结构是Arguments类型,使用扩展运算符变为数组,再使用slice方法
    var args=[...arguments].slice[1]
    result=context.fn(...args)
    //得出结果后将自己加的context.fn删除,避免改变原先的结构
    delete context.fn
    return result
}
console.log(person.getName.myCall(man));

apply

相比call,apply的不同在于其第二个参数是以数组的方式传递的,要使用时直接展开传入即可

//开始手写方法
Function.prototype.myApply=function(context){
    var result
    //不确定是否传了参数,如果没传,就让他指向window
    var context=context||window;
    //getName要执行,this要指向context
    context.fn=this

    //判断是否存在第二个参数,存在的话使用扩展运算符展开
    if(arguments[1]){
        result=context.fn(...[arguments[1]])
    }else{
        result=context.fn()
    }
    //得出结果后将自己加的context.fn删除,避免改变原先的结构
    delete context.fn
    return result
}
console.log(person.getName.myApply(man));

六.获得20~50之间的随机数

在第一时间兄弟们的想法是不是创建一个随机数再使用乘法。但是面试官不想在函数中看到数字怎么办哈哈哈。想一想想一想👽👽

不过确实如此呀兄弟们,那样的写法太low了,显得水平很低哎。总得写点高逼格的嘛。见代码

function randomNum(min,max){
    var range=max-min
    var rand=Math.random()
    return min+Math.round(range*rand)
}
console.log(randomNum(20,50));

七.写一个事件委托

此题算是简简单单吧,但是又有点不简单,需要原生js基础相当扎实,那个判断说实话我是写不出来

<ul id="ul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
<script>
var ul=document.getElementById('ul')
ul.onclick=function(event){
    var target=event.target
    if(target.nodeName==='LI'){
        console.log(target);
        alert(target.innerHTML)
    }
}
</script>

八.写一个函数可以返回参数的具体数据类型

此题的考点在typeof的使用,

该方法对于基本类型除了null,都可以返回正确的类型(null会返回object)

对于引用类型都会返回object,除了function会返回function

此题对于引用数据类型的判断可以使用instanceof来解决,更加的简单。在后面的文章中我会出一篇来专门解释typeof于instanceof的区别。

function getType(target){
    var ty=null
    if(typeof target=='object'){
        //此处使用了短路表达式
        Object.prototype.toString.call(target)==='[object Object]'&&(ty='Object')
        Object.prototype.toString.call(target)==='[object Array]'&&(ty='Array')
    }else{
        typeof target === 'string' && (ty='string')
        typeof target === 'number' && (ty='number')
        typeof target === 'boolean' && (ty='boolean')
        typeof target === 'undefined' && (ty='undefined')
        typeof target === 'function' && (ty='function')
    }
    return ty
}
console.log(getType(function fn(){}));
console.log(getType(1));
console.log(getType('sss'));
console.log(getType(undefined));
console.log(getType(true));
console.log(getType([1,2,3]));
console.log(getType({a:1,b:2}));

九.写一个函数来计算参数的和

此题难么?不难,但是想要写好并不简单,在于你是否能想到其他的特殊情况。

考点一个是Number的类型转换,一个是出现NaN

1.使用循环 

function getSum(){
    var length=arguments.length
    var s=0
    for(var i=0;i<length;i++){
        //判断是否是NaN,不是的话进行加法
        if(!isNaN(arguments[i])){
            //将参数都转换为number类型
            s+=Number(arguments[i])
        }
    }
    return s
}
console.log(getSum('1',2,3,NaN));

2.使用reduce

  • prev:表示上一次调用回调时的返回值,或者初始值init
  • cur:表示当前正在处理的数组元素
  • index:表示正在处理的数组元素的索引,若提供init值,则索引为0,否则索引为1

关于reduce的使用我会在之后的文章中来专门说明,大家莫急🔥🔥在赶了

var arr=[1,2,3,4]
var init=1
var sum=arr.reduce((pre,cur,index)=>{
    return pre+cur
})
console.log(sum);

十.每隔1s打印当前时间,格式为YYYY-MM-DD hh:mm:ss

此题还是重在考察js基础,需要注意的是月份的+1,以及天数是getDate,而不是getDay

setInterval(()=>{
    console.log(timer());
},1000)
function timer(){
    var date=new Date()
    var year=date.getFullYear()
    var month=(date.getMonth()+1).toString().padStart(2,"0")
    var day=date.getDate().toString().padStart(2,"0")
    var hour=date.getHours().toString().padStart(2,"0")
    var minute=date.getMinutes().toString().padStart(2,"0")
    var s=date.getSeconds().toString().padStart(2,"0")
    return `${year}-${month}-${day} ${hour}:${minute}:${s}`
}

十一.能否使用某种方式将下面的语句使用展开运算符而不导致类型错误

let obj={x:1,y:2,z:3}
console.log(...obj)

此题作为国庆压轴题自然要更有趣有深度一点,其主要考点为迭代器reflect的使用 

  • 能否使用展开运算符在于其是否有迭代器(看xxx[Symbol.iterator]是否存在)
  • keys的获取使用Reflect.ownKeys而不是Object.keys。因为如果对象里有Symbol类型的话Object.keys是获取不到的。知道Reflect.ownKeys就是你以后装逼的地方了😈在面试中能写出这个肯定会加分的
let obj={x:1,y:2,z:3}
obj[Symbol.iterator]=function(){
    return {
        next:function(){
            let objArr=Reflect.ownKeys(obj)
            if(this.index<objArr.length-1){
                let key=objArr[this.index]
                this.index++
                return {value:obj[key]}
            }else{
                return {done:true}
            }
        },
        index:0
    }
}
console.log(...obj);

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏茂林别干饭了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值