JS面试题

面试大全

1、javascript 的 typeof 返回哪些数据类型

number、boolean、undefined、string、object、function

2、javascript 有哪些数据类型

基本数据类型:number、boolean、undefined、string、null、
引用数据类型:object、RegExp、array、Date、Math

3、例举 3 种强制类型转换和 2 种隐式类型转换?

强制转换:parseInt,parseFloat,Number()

隐式转换:==

4、split() 和  join()的区别

前者是切割数组的形式,后者是将数组转换成字符串

5、数组方法pop() push() unshift() shift()

pop() 尾部删除  shift()头部删除

push() 尾部添加  unshift() 头部添加

6、数组方法

every() filter() forEach() isArray() map() reduce() indexOf()

7、深拷贝和浅拷贝

浅拷贝:赋值符号 =

深拷贝:

1、var arr2 = arr1.slice(0),(多层数组有问题,如[ 1 ,2,[0,1] ,3])

2、var arr2 = arr1.concat();(多层数组有问题)

3、for循环重新压进新的空数组  (多层数组需要多层循环压进去,否则有问题)

4、ES6的扩展运算符  var  [...arr2] = arr1,(多层数组和多层对象有问题,如[ 1 ,2,[0,1] ,3])

    let oldObj = {
  		a: 1, b: 2
	}
	let newObj = {...oldObj}
	newObj.a = 2
	console.log(oldObj) //  {a: 1, b: 2}

	let outObj = {
  		inObj: {a: 1, b: 2}
	}
	let newObj1 = {...outObj}
	newObj1.inObj.a = 2
	console.log(outObj) // {inObj: {a: 2, b: 2}}

    let outArr = [1,2,[4,5],3]
	let newArr = [...outArr]
	  newArr[0] = 2;
	  newArr[2][1] = 6;
	 console.log(outArr)//[1,2,[4,6],3]

5、JSON.parse(JSON.stringify(arr1)) ,若为正则、函数、undefined、NaN等值有坑(实际工作中常用的方法)

8、字符串里面的字符数最多次数以及该字符是什么?

var str = "asdkfhsodjcpeksoxshieorjsa";
    var obj = {};var maxNum = 0;  var letter = '';
        for(var i=0;i<str.length;i++){
             if(!obj[str.charAt(i)]){
                 obj[str.charAt(i)] = 1;
        }else{
            obj[str.charAt(i)]++;
        }
};
 for(var item in obj){
    if(obj[item ]>maxNum){
        maxNum=obj[item];
        letter = item 
    }
}
console.log('出现次数最多的是:'+letter+'出现'+maxNum+'次')

9、99乘法表制作

<script>

for (var i = 1;i <=9;i++) {
    for(var j = 1;j <=i;j++) {
        document.write(i+"*"+j+"=" + i*j +"&nbsp;&nbsp;")
    }
    document.write("<br/>")
}
</script>

10、js将数字转换为汉字

function  convertToChinaNum ( num ) {
var  arr1 =newArray('零','一','二','三','四','五','六','七','八','九');
var  arr2 =newArray('','十','百','千','万','十','百','千','亿','十','百','千','万','十','百','千','亿');//可继续追加更高位转换值

if(!num ||isNaN(num)){
    return"零";
}

var  english = num.toString().split("")
var  result ="";
for(var  i =0; i < english.length; i++) {
        var  des_i = english.length -1- i;//倒序排列设值
            result = arr2[i] + result;
            var  arr1_index = english[des_i];
           result = arr1[arr1_index] + result;
    }

    //将【零千、零百】换成【零】 【十零】换成【十】
    result = result.replace(/零(千|百|十)/g,'零').replace(/十零/g,'十');
    //合并中间多个零为一个零
    result = result.replace(/零+/g,'零');
    //将【零亿】换成【亿】【零万】换成【万】
    result = result.replace(/零亿/g,'亿').replace(/零万/g,'万');
    //将【亿万】换成【亿】
    result = result.replace(/亿万/g,'亿');
    //移除末尾的零
    result = result.replace(/零+$/,'')
    //将【零一十】换成【零十】
    //result = result.replace(/零一十/g, '零十');//貌似正规读法是零一十
    //将【一十】换成【十】
    result = result.replace(/^一十/g,'十');
    return  result;
}

11、事件绑定和普通事件有什么区别?

事件绑定是指把事件注册到具体的元素之上,普通事件指的是可以用来注册的事件

普通事件会覆盖掉,只执行后者方法,不支持DOM事件流
dom.onclick = function(){}

事件绑定不会覆盖掉,会依次执行,支持DOM事件流
addEventListener('click',function(){},true)

12、跨域问题?

概念:只要协议、域名、端口有任何一个不同,都被当作是不同的域

请求接口的时候有时候会出现子域名等,导致跨域问题

解决方案:JSONP、websocket、CORS、PostMessage

注意JSONP只支持GET方法
JSONP原理及实现
什么是跨域?javascript跨域的四种方式介绍-js教程-PHP中文网

13、call和apply的区别?

都是改变this的指向,两个方法属于Function.prototype原型上的方法

call传参一个一个的传,apply传参是个数组

14、继承的方法?

总共有5种

对象冒充、call、apply、原型继承、混合继承(call和原型继承混合)

JavaScript中B继承A的方法 - Me丶微笑 - 博客园

15、JavaScript指针、闭包、作用域?

this指向调用上下文

闭包:内作用域调用外作用域的变量,滥用闭包函数会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量都
永远不会被释放,所以我们应该在必要的时候,及时释放这个闭包函数

作用域:定义一个函数就开辟了一个局部作用域,整个JS执行环境有一个全局作用域

16、事件委托是什么?

符合 W3C 标准的事件绑定 addEventLisntener /attachEvent

利用事件冒泡的原理,把自己的所触发的事件,让他的父元素代替执行!

js中的事件委托或是事件代理详解 - 凌云之翼 - 博客园

17、如何阻止事件冒泡和默认事件?

阻止冒泡:e.stopPropagation()

阻止默认事件:e.preventDefault()
JS阻止冒泡和取消默认事件(默认行为)-前端开发博客

18、添加 删除 替换 插入到某个节点的方法 ?

obj.appendChild()

obj.insertBefore() //原生的 js 中不提供 insertAfter();

obj.replaceChild()//替换

obj.removeChild()//删除

19、document load 和 document ready 的区别?

Document.onload 是在结构和样式加载完才执行 js

window.onload:不仅仅要在结构和样式加载完,还要执行完所有的样式、图片这些资源文

件,全部加载完才会触发 window.onload 事件

Document.ready 原生种没有这个方法,jquery 中有 $().ready(function)

20、=的区别?

前者只是判断值是否相等,后者会判断数据类型和值是否都相等

21、javascript 的同源策略?

一段脚本只能读取来自于同一来源的窗口和文档的属性,这里的同一来源指的是主机名(域名指向的是ip地址,即主机地址)、协

议和端口号的组合

http,ftp:协议

主机名;localhost

端口名:80:http 协议的默认端口

https:默认端口是 8083

同源策略带来的麻烦:ajax 在不同域名下的请求无法实现,

如果说想要请求其他来源的 js 文件,或者 json 数据,那么可以通过 jsonp 来解决

23、JavaScript 是一门什么样的语言,它有哪些特点?

js是面向对象的弱类型语言

语言特性:面向对象(要掌握创建对象的多种方式,继承的多种方式、原型链),动态/弱类型语言

24、已知 ID 的 Input 输入框,希望获取这个输入框的输入值,怎么做?(不使用第三方框架)

document.getElementById('ID').value

25、希望获取到页面中所有的 checkbox 怎么做?(不使用第三方框架)

var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];    //返回的所有的 checkbox
var len = domList.length;     //缓存到局部变量
while (len--) {     //使用 while 的效率会比 for 循环更高
        if (domList[len].type == 'checkbox') {
        checkBoxList.push(domList[len]);
    }
}

//获取已经选中的多选项  CheckBox

26、箭头函数和普通函数的区别是什么?

答:普通函数this总是指向他的调用者,默认指向window,在严格模式下,没有直接调用者的函数中this是undefined,使用call、apply、bind绑定,this指的是绑定的对象

箭头函数的this,指向定义时所在的对象,而不是调用时所在的对象;箭头函数不能构造函数(使用new 命令),否则抛出错误;不能使用arguments对象;不能使用yield命令

27、讲一下let 、var、const的区别?

var 没有块级作用域,支持变量提升

let 有块级作用域,不支持变量提升,不允许重复声明同名变量,暂存性死区,不能通过window进行访问

const 有块级作用域,不允许变量提升,不允许重复声明同名变量,暂存性死区,不能改变变量的值

28、实现一个new的伪代码?

创建一个对象;链接原型;绑定this;返回该对象

function  _new( ) {
    let obj = new Object();
    let Con = [].shift.call(arguments);
    obj.__proto__ = Con.prototype;
    let result = Con.apply(obj,arguments);
    return typeof result ==='object' ? result :obj
}
function create(Con, ...args) {
    this.obj = {};    

    //创建一个空的对象//将空对象指向构造函数的原型链    
    Object.setPrototypeOf(obj, Con.prototype);   

     //obj绑定到构造函数上,便可以访问构造函数中的属性
    let result = Con.apply(obj, args);   

     //如果返回的result是一个对象则返回该对象,new方法失效,否则返回obj
    return    result    instanceof    Object ? result : obj;
}

29、原型、原型链?

每一个JS函数中都有一个prototype(原型)属性,指向这个函数的原型对象,通过这个函数产生的实例对象都有一个__proto__(隐式原型)属性,这个属性也是指向同一个原型对象,所有的实例对象的属性都会继承这个原型对象的属性,原型对象上也有一个__proto__属性,指向的objec原型对象,所有的对象属性都会继承objec原型对象属性。而object原型对象的__proto__指向的是null。当我们访问对象的某个属性时,就会从实例对象,原型对象,object原型对象上层层寻找,由此形成原型链。而原型就是原型对象上的属性。

什么是原型和原型链?原型链继承? - 风中逆羽 - 博客园

30、垃圾回收机制(闭包的延伸)?

分为以下两个阶段:

1、标记阶段:垃圾回收器,从根对象开始遍历,访问到的每一个对象都会被标示为可到达对象。

2、清除阶段:垃圾回收器在对内存当中进行线性遍历,如果发现该对象没有被标记为可到达对象,那么就会被垃圾回收机制回收。这里面牵扯到了引用计数法,每次引用都被会‘➕1’ 如果标记清零,那么就会被回收掉。

31、函数的节流和防抖动?

防抖动函数:将多次触发变成最后一次触发;

function debounce(fn,wait){
  let timer = null;
  return function (){
    let arg = arguments;
    if(timer){
      clearTimeout(timer);
      timer = null;
    }
    timer = setTimeout(()=>{
       fn.apply(this,arg)
    },wait)
  }
}
function clg(){
  console.log('clg')
}
window.addEventListener('resize',debounce(clg,1000))

节流函数:将多次执行变成每隔一个时间节点去执行的函数

function throttle(fn,time){
  let lastTime = null;
  return function(){
    let nowTime = Date.now();
    if(nowTime - lastTime > time || !lastTime){
      fn();
      last = nowTime
    }
  }
}
function sayHi(){
  console.log('hi')
}
setInterval(throttle(sayHi,1000),500)

32、简单介绍下event loop?

js作为单线程语言。在执行过程中,会产生执行环境。这些执行环境中的代码被顺序的加入到执行栈中,如果遇到异步代码,会被挂起并加入到任务队列当中,等到主线程任务执行完毕,event loop就会从任务队列取出需要执行的代码放入到执行栈中执行。所以本质上来讲,js中的异步还是同步的行为。

任务队列有分为宏任务和微任务队列。
一次正确的event loop执行顺序如下:

1、执行所有同步代码
2、执行栈为空,查询是否有需要执行的微任务。
3、微任务(有:则执行,无:则跳出)
4、必要的话开始渲染UI
5、开始下一轮的任务队列执行宏任务中的异步代码。

33、数组去重?

//扩展运算符只对单层数据深拷贝
functin uniqueStr ( arr ) {
    var newArr = new Set( arr );
    return [...newArr]
}
functin uniqueStr ( arr ) {
    var newArr = [],obj = {};
    for (var = i;i < arr.length;i++) {
        if(!obj[arr[i]]){
            newArr.push(arr[i])
            obj[arr[i]] = 1
        }
    }
    return newArr
}
function uniqueArr(arr) {
  const res = new Map()
  return arr.filter((a)=>{
        return !res.has(a) && res.set(a,1)
    })
}

https://www.cnblogs.com/zhishaofei/p/9036943.html

34、创建对象的5中方法?

1、new 操作符+Object创建对象

var person = new Object();
    person.name = "lisi";
    person.age = 21;
    person.family = ["lida","lier","wangwu"];
    person.say = function(){
        alert(this.name);
    }

2、字面式创建对象

var person ={
        name: "lisi",
        age: 21,
        family: ["lida","lier","wangwu"],
        say: function(){
            alert(this.name);
        }
    };

3、工厂模式

funtion createPerson(name,age,family) {
  var o = new Object();
    o.name = name;
    o.age = age;
    o.family = family;
    o.say = function(){
    alert(this.name)
  }
}
var person = createPerson('lisi','12',['wangwu','liumazi']);
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person1.constructor);      //constructor 属性返回对创建此对象的数组、函数的引用
//K可以重复调动,工厂式的创造对象

4、构造函数模式

function Person(name,age,family) {
    this.name = name;
    this.age = age;
    this.family = family;
    this.say = function(){
        alert(this.name);
    }
  return o;
}
var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person1.constructor);      //constructor 属性返回对创建此对象的数组、函数的引用

构造函数模式每个实例包含不同的Function实例,占用内存
5、原型模式

function Person() {
}

Person.prototype.name = "lisi";
Person.prototype.age = 21;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
    alert(this.name);
};
console.log(Person.prototype);   //Object{name: 'lisi', age: 21, family: Array[3]}

var person1 = new Person();        //创建一个实例person1
console.log(person1.name);        //lisi

var person2 = new Person();        //创建实例person2
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];
console.log(person2);            //Person {name: "wangwu", family: Array[3]}
// console.log(person2.prototype.name);         //报错
console.log(person2.age);              //21

6、混合模式(构造函数+原型模式)

function Person(name,age,family){
    this.name = name;
    this.age = age;
    this.family = family;
}

Person.prototype = {
    constructor: Person,  
//每个函数都有prototype属性,指向该函数原型对象,
//原型对象都有constructor属性,这是一个指向prototype属性所在函数的指针
    say: function(){
        alert(this.name);
    }
}

var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
console.log(person1);
var person2 = new Person("wangwu",21,["lida","lier","lisi"]);
console.log(person2);

还有动态原型模式、寄生构造函数模式、稳妥构造函数模式

35、哪些方法改变原数组,哪些方法不改变原数组

改变原数组的:

1、shift:将第一个元素删除并且返回删除元素
2、unshift:在原数组的最前端依次添加,并且返回新数组的长度
3、push:在原数组的最后依次添加项,并返回新数组的长度
4、pop:将最后一个元素移除并返回移除的项
5、reverse:反转数组的顺序
6、sort:对数组进行依次排序
7、splice:三个参数。第一个代表开始的下标,第二个代表 要删除的个数,第三个代表要替换的东西       返回被删除的数组

不改变原数组的:

1、concat:拼接,连接多个数组
2、slice:提取,返回被提取的字符
3:join:将数组中所有元素以参数作为分隔符放入一个字符
4、map,filter,some,every,foreach等不改变原数组

拓展

toString(),数组转字符串

36、js数组迭代方法与归并方法

ES5为数组定义了5个迭代的方法:
运行的函数会接受三个参数:1)数组项的值 2)该项在数组中的位置 3)数组对象本身。

.every()

对数组的每一项运行给定函数,如果该函数对每一项都返回true,则返回true。

    例:
    var arr = [1,2,3,4,5,4,3,2,1];
    var num = arr.every(function(item,index,array){
        return (item > 2);
    })
    console.log(num);  //false

.some()

对数组的每一项运行给定函数,如果该函数对任一项返回true,则返回true。

    例:
    var arr = [1,2,3,4,5,6,7,8];
    var num = arr.some(function(item,index,array){
        return (item > 2);
    })
    console.log(num);  //true

.filter()

对数组的每一项运行给定函数,返回该函数会返回true的项组成的数组。

    例:
    var arr= [1,2,3,4,5,4,3,6,1];
    var num= arr.filter(function(item,index,array){
        return (item > 3);
    })
    console.log(filterResult);  //[4,5,4,6]

·map()

对数组的每一项运行给定函数,返回每次函数调用的结果组成的数组。

    例:
    var arr = [1,2,3,4,5,6,7,8];
    var num = arr.map(function(item,index,array){
        return item*2;
    })
    console.log(num);  //[2,4,6,8,10,12,14,16]

·forEach()

对数组的每一项运行给定函数。该方法没有返回值。

    var arr = [1,2,3,4,5,6,7,8];
    var num = arr.forEach(function(item,index,array){
        console.log(item*2); //[2,4,6,8,10,12,14,16]
    })
    console.log(num);  //undefined

归并方法

·reduce() 是从数组的第一项开始,逐个遍历到最后。
·reduceRight() 是从数组的最后一项开始,逐个遍历到最前。
这两个方法都会迭代数组的所有项,然后构建一个最终返回的值。
传给这两个方法的函数接收4个参数:1)前一个值 2)当前值 3)项的索引 4)数组对象

    例:
    var values = [3,6,5,2,4,2];
    var sum = values.reduce(function(prev,cur,index,array){
        return prev + cur;  //3+6=9+5=14+2=16+4=20+2=22
    });
    console.log(sum); //22
posted @ 2022-11-03 11:35  SultanST  阅读(44)  评论(0编辑  收藏  举报