js基础面试题

1. JavaScript String对象–常用
  1. **charAt(index) :**返回指定位置的字符,index从0开始

    var str="Hello world!"
    console.log(str.charAt(1))//e
    
  2. split(separator,howmany):把字符串分割为字符串数组,参数1是分割的依据,参数2是返回数组的最大长度

    //如果是空字符串那么全部分割
    var str = "get-element-by-id"
    console.log(str.split("-"))//["get","element","by","id"]
    
  3. **slice(start,end):**提取字符串某部分,包括start,不包括end,没有end则到结尾

    var str = "hello world"
    console.log(str.slice(3,7))//lo w
    
  4. **substr(start,length):**提取字符串某部分,start开头,length长度,没有end则到结尾

    var str = "hello world"
    console.log(str.substr(3,7))//lo worl
    
  5. **replace(regexp,replacement):**在字符串中用一些字符替换另一些字符

    var str = "hello world"
    console.log(str.replace(/world/g,"Array"))//hello Array
    
  6. toLowerCase():把字符串转为小写

  7. toUpperCase():把字符串转为大写

//实例
var str = "get-element-by-id"
var arr = str.split("-")
for(var i=1; i<arr.length;i++){
    arr[i] = arr[i].charAt(0).toUuperCase()+arr[i].slice(1,arr[i].length)
}
console.log(arr.join(''))//getElementById
2. JavaScript Array对象
  1. join(连接符):把数组的所有元素放入一个字符串,元素通过指定的分隔符进行分隔。与String中的split对应

    //不写连接符则以逗号
    var arr = new Array(2)
    arr[0] = "ysc"
    arr[1] = "xiao"
    document.write(arr.join(''))// yscxiao
    
  2. push():可以向数组的末尾添加一个或多个元素,返回值:数组的新长度

  3. unshift():向数组开头添加元素,返回值:数组新长度

  4. pop():删除最后一个元素,返回值:被删除的元素

  5. reserve():反转,颠倒反转

  6. shift():删除第一个元素,返回值:被删除的元素

    //改变原数组
    var arr = ['孙悟空', '猪八戒', '沙悟净'];
    var res1 = arr.push('唐僧', '白龙马')
    console.log(res1)//5
    console.log(arr)//["孙悟空", "猪八戒", "沙和尚", "唐僧", "白龙马"]
    
    var res2 = arr.pop()
    console.log(res2)//白龙马
    console.log(arr)//["孙悟空", "猪八戒", "沙和尚", "唐僧"]
    
    var res3 = arr.unshift('观音菩萨')
    console.log(res)//5
    console.log(arr)//["观音菩萨","孙悟空", "猪八戒", "沙和尚", "唐僧"]
    
    var res4 = arr.shift()
    console.log(res)//观音菩萨
    console.log(arr)//["孙悟空", "猪八戒", "沙和尚", "唐僧"]
    
  7. slice(start,end) 提取指定元素,返回值:提取到的元素,不改变元数组,包含start,不包含end

    //并不会改变原数组
    var arr = ["孙悟空","猪八戒","沙格尚","白龙马","唐僧"]
    var res1 = arr.slice(0,2)
    console.log(res)//"孙悟空" "猪八戒"
    console.log(arr)//"孙悟空","猪八戒","沙格尚","白龙马","唐僧"
    
  8. splice(a,b,c):返回值:删除的内容,可删除—可替换—可插入,会影响原数组。a:表示开始位置的索引 包含,索引都是从0开始;b:表示删除个数;c:插入的内容,可替换-可插入

    //改变原数组
    var res2 = arr.splice(1,1)
    consoloe.log(res2)//猪八戒
    console.log(arr)"孙悟空","沙格尚","白龙马","唐僧"
    var res3 = arr.splice(1,1,"替换")
    console.log(res3)//沙格尚
    console.log(arr)"孙悟空","替换","白龙马","唐僧"
    
  9. sort(sortby) :方法用于对数组的元素进行排序。可选,规定排序顺序,必须是函数

    function sortNumber(a,b){return a - b}
    //var arr = ["10","5","40","25","1000","1"]
    var arr = new Array(6)
    arr[0] = "10";arr[1] = "5";arr[2] = "40";arr[3] = "25";arr[4] = "1000";arr[5] = "1"
    document.write(arr + "<br />")//10,5,40,25,1000,1
    document.write(arr.sort(sortNumber))//1,5,10,25,40,1000
    
  10. indexOf():可以返回数组中某个指定的元素位置

var arr = [1,2,5,3,6,8]
arr.indexOf(arr[i]) == i
3. 冒泡排序
var arr = [1,2,5,3,6,8]
for(var i=0;i<arr.length-1;i++){
    for(var j=0;j<arr.length-1-i;j++){
        if(arr[j]>arr[j+1]){
            var temp = arr[j]
            arr[j] = arr[j+1]
            arr[j+1] = temp } } }
console.log(arr)//1,2,3,5,6,8
4. 数组反转
var arr = [1,2,4,5]
for(var i=0;i<arr.length/2;i++){
    var temp = arr[i]
    arr[i] = arr[arr.length-1-i]
    arr[arr.length-1-i] = temp }
console.log(arr)//5,4,2,1
5. 数组去重
//方法一:双重for循环加splice
var arr = [1,2,2,5,6,8,10,8,8]
for(var i=0;i<arr.length;i++){
    for(var j=i+1;j<arr.length;j++){
        if(arr[j] == arr[j+1]){
            splice(j,1)
            j-- } } }
console.log(arr)//1,2,5,6,8,10

//方法二:indexOf加push
var arr = [1,2,2,5,6,8,10,8,8]
var att = []
for(var i=0;i<arr.length;i++){
    if(arr.indexOf(arr[i]) == i){
        att.push(att[i]) } }
console.log(arr)//1,2,5,6,8,10

//方法三:indexOf+splice
var arr = [1,2,2,5,6,8,10,8,8]
for(var i=0;i<arr.length;i++){
    if(arr.indexOf(arr[i]) != i){
        arr.splice(i,1)
        i-- } }
console.log(arr)//1,2,5,6,8,10

//方法四:es6	new Set() + Array.from()转数组
var arr = [1,2,2,5,6,8,10,8,8]
var att1 = Array.from(new Set(arr))
var att2 = new Set(arr)
console.log([...att2])
console.log(att1)
6. 原型链综合练习

.的运算级是非常高的,但是前面遇到()时候,需要先运算()的,

比如 new Foo.getName() new Foo().getName()

//var getName	function getName() {alert(5)}这两句被提升,当继续执行到var getName = function() {alert(4)}时候,alert5会被替换成alert4,所有5不会出现
function Foo(){
    getName = function() {alert(1)}
    return this}
Foo.getName = function() {alert(2)}
Foo.prototype.getName = function() {alert(3)}
//实例对象的显示原型==隐式原型链
var getName = function() {alert(4)}
function getName() {alert(5)}
//var getName和 function getName(){}都有提升变量的作用,当2个作用于同一个变量时,var会不使用

Foo.getName()	//读取2
getName()	//读取4	alert(4)覆盖了alert(5)
Foo().getName()	//读取1	
getName()	//读取1	因为上面调用了Foo函数,里面的getName没有var声明,所有会跳出函数,在全局中找,找到getName = function() {alert(4)},然后alert(1)替换了alert(4)
new Foo.getName()	//读取2	new (Foo.getName())==>new (2)
new Foo().getName()	//读取3	(new Foo()).getName()==>foo.getName()
new new Foo().getName()	//读取3 new((newFoo()).getName()).getName==>new new(2)
var a = 123;
fn(a);
function fn(){a=456}
console.log(a)//456
//因为fn没有定义形参,所有a=456会去查找上一层找a,找到var a=123,让456覆盖了123,输出为456

var a=123;
fn(a);
function fn(a){a=456}
console.log(a)//123
//因为fn中有形参a,a=456改变的是局部的,输出的a是全局的,会查找到123
7. 节流、防抖
//节流:高频率触发事件时,减少触发频率,周期性的触发一次
function throttle(fn,delay){
    let timer = null
    return function(){
        if(!timer){
            let args = arguments
            timer = setTimeout(() => {
                fn.apply(this,args)
                timer = null
            },delay)
        }
    }
}
//防抖:高频率触发事件,在规定时间内多次触发,只执行最后一次
function dedounce(fn,delay){
    let timer = null
    return function(){
        let args = arguments
        if(timer)clearTimeout()
        timer = setTimeout(() => {
            fn.apply(this, aegs)
        },delay)
    }
}
8. 从URL到页面显示发生什么
  1. DNS解析:将域名地址解析为ip地址
  2. TCP连接:TCP三次握手
    1. 浏览器发起,告诉服务器,我要发送请求
    2. 服务器发起,告诉浏览器,我要准备接收,你可以发送了
    3. 浏览器发起,告诉服务器,我马上发送,你接收把
  3. 发送请求:请求报文,HTTP协议的通信内容
  4. 接收响应:响应报文
  5. 渲染页面:
    1. 遇见HTML标记,浏览器调用HTML解析器解析成Token并构建成dom树
    2. 遇见style/link标记,浏览器调用css解析器,处理css标记并构建cssom树
    3. 遇见script标记,调用JavaScript解析器,处理script代码
    4. 将dom树和cssom树合并成一个渲染树
    5. 根据渲染树来计算布局。计算每个节点的几何信息
    6. 将各个节点颜色绘制到屏幕上
  6. 断开连接:TCP四次挥手
    1. 浏览器发起,发送给服务器,我东西发送完了(请求报文),你准备关闭吧
    2. 服务器发起,发送给浏览器,我请求报文接收完了,准备关闭了,你也准备吧
    3. 服务器发起,发送给浏览器,我响应报文发送完了。你准备关闭吧
    4. 浏览器发起,发送给服务器,我东西接收完了,准备关闭了,你也准备吧
9. 闭包
什么是闭包?一个函数可以访问另一个函数作用域中的变量
	1。密闭的容器,存储数据的
	2.闭包是一个对象,存放数据的格式:keyL:value
形成的条件?
	1.函数嵌套
	2.内部函数引用外部函数的局部变量
闭包的优点:
	延长外部函数局部变量的生命周期
闭包的缺点:
	容易造成内存泄漏
注意点:
	1.合理的使用闭包
	2.用完闭包要及时清除
应用场景:团队开发时,每个开发人员把自己的代码放在私有作用域下,防止变量名冲突,把需要使用的方法通过return暴露给全局
function fun(){
	var count = 1;
	return function(){
		count++;
		console.log(count)
	}
}
var fun2 = fun()
fun2();//2
fun3();//3	这里会记录之前的count2值,而不是重新赋值为1

new 函数this指向实例对象

10. 异步任务:

宏任务(主线程js代码)–>微任务(new Promise.then())–>宏任务(setTimeout)

宏任务
	分类:setTimeout	setInterval		requrestAnimationFrame
	宏任务队列可以有多个,第一个宏任务队列只有一个任务:指向主线程的js代码
	当宏任务队列执行完毕后,会去查找是否有微任务队列,有就执行微任务,没有就查看是否还有宏任务,有就继续执行宏任务
微任务
	分类:new Promise().then()		process.nextTick
	微任务队列只有一个,在上一个宏任务队列执行完毕后如果有微任务队列就会执行微任务队列中的所有任务 
console.log("-------------start-----------");
      setTimeout(() => {
        console.log('setTimeout');
      }, 1000);
      new Promise((resolve, reject) => {
        for (var i = 0; i < 5; i++) {
          console.log(i);
        }
        resolve()
      }).then(() => {
        console.log('promise执行了');
      })
console.log("-------------end-----------");
// start   0 1 2 3 4	end		promise执行了	setTimeout
11. new关键字
1. 调用new关键字首先会创建一个新的空对象;
2. 设置原型(prototype),将对象的原型设置为函数的prototype对象;
3. 让函数的this指向这个对象,为这个新函数添加属性;
4. 判断函数的返回类型,如果是值类型,返回创建的对象,如果是引用类型,就返回引用类型的对象;
12. 跨域

同源策略:协议名、域名、端口号必须完全一致

跨域:违背同源策略就会产生跨域

//jsonp解决跨域
//创建script标签
var script = document.createElement('script')
//设置回调函数
function getData(data) {
    //数据请求回来会触发的函数
    console.log(data)
}
//设置在script的sec属性,设置请求地址
script.src = 'http://localhost:3000?callback=getData'
//让script生效
document.body.appendChild(script)
13.面试题
13.1 按顺序执行2个ajax请求
function getPhoto(){}
function getText(){}
async function myAjax(){
    const photoList = await getPhoto()
    const textList = await getText()
}
13.2 冒泡排序,至少2种方法?
// 方案一:最基础
function buSort(arr){
    for(let i=0;i<arr.length;i++){
        for(let j=0;j<arr.length-i-1;j++){
            if(arr[j]>arr[j+1]){
                // 利用结构赋值
                [arr[j],arr[j+1]] = [arr[j+1],arr[j]] 
            }
        }
    }
    return arr
}
// 方案二:增加标记,某一轮比较,一个元素都没换,则表示有序
function buSort(arr){
    for(let i=0;i<arr.length;i++){
        let isSort = true
        for(let j=0;j<arr.length-i-1;j++){
            if(arr[j]>arr[j+1]){
                [arr[j],arr[j+1]] = [arr[j+1],arr[j]]
                isSort = false
            }
            if(isSort){
                break;
            }
        }
    }
    return arr
}
13.3 实现深浅拷贝
// 浅拷贝	如果拷贝的是基本数据类型,拷贝的就是基本数据类型的值,如果是引用数据类型,拷贝的就是内存地址
let obj = {a:1,b:'2'}
// 1. Object.assign()
let res1 = Object.assign({},obj)
// 2. 扩展运算符
let res2 = {...obj}
// 3. concat 可以合并2个或以上数组,不写值则浅拷贝
let res3 = obj.concat()
// 深拷贝	如果遇到属性值为引用类型的时候,它新建一个引用类型并将对应的值复制给它。产生完全新的,完全不一样
let obj = {a:1,b{c:'2'}}
let res = JSON.parse(JSON.stringify(obj))
obj.a = 2
obj.b.c = '4'
console.log(obj) // {a:2,b{c:'4'}}  
console.log(res) // {a:1, b{c:'2'}}
// 手写实现深拷贝
function deepCopy(obj){
    if(!obj || typeof obj !== 'object')return
    let newObj = Array.isArray(obj) ? [] : {}
    for(let key in obj){
        // 判断自身属性而非原型链上属性
        if(obj.hasOwnProperty(key)){
            newObj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
        }
    }
    return newObj
}
13.4 去重
// 方案一:两个for选循环
let arr = [1,2,3,4,5,6,6]
function remove(arr){
    for(let i=0;i<arr.length;i++){
        for(let j=i+1;j<arr.length;j++){
            if(arr[j] == arr[j+1]){
                splice(j,1)
                j--
            }
        }
    }
    return arr
}
// new Set
let arr = [1,2,3,4,5,6,6]
let res = Array.from(new Set(arr))
13.5 cookie、localStorage、sessionStorage异同
1. cookie 存储大小太小,发生请求时会发送到服务器,
2. lo和se  存储空间大,并不会发送到服务器,api调用简单
3.  lo  可以永久存储,除非去删除
	se	只存在当前会话,浏览器关闭就清空
13.6 列举请求类型,说明get和post请求异同点
1. get、post、put、delete
2. 两者区别:
 1.本质区别:get是发送一次http请求,而post先发送请求头再发送请求体,相当于两次请求;
 2.get请求一般获取服务器资源,而post一般更新服务器资源;
 3.get会将请求提交的数据明文出现在url上,而post请求参数在请求体中,更加安全;
 4.get发送的数据长度有限制,而post无限制 
13.7 css position属性列举并说明
position:static;正常布局
position:relative; 相对定位
position:absolute; 绝对定位
position:fixed; 固定定位
13.8 说说前端中的事件流
事件流:描述是从页面中接收事件的顺序。
事件捕获阶段、处于目标阶段、事件冒泡阶段
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值