defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本。async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。二、JS数据类型有哪些?基本类型:string、num............._js高级面试题">
当前位置:   article > 正文

js高频面试题_js高级面试题

js高级面试题

一、延迟加载JS有哪些方式?

延迟加载:async、defer

  • 例如:<script defer type="text/javascript" src='script.js'></script>

defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本
async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。

 二、JS数据类型有哪些?

基本类型:string、number、boolean、undefined、null、symbol、bigint
引用类型:object

NaN是一个数值类型,但是不是一个具体的数字。

三、JS数据类型考题

考题一:

  1. console.log( true + 1 );                 //2
  2. console.log( 'name'+true );              //nametrue
  3. console.log( undefined + 1 );             //NaN
  4. console.log( typeof undefined );        //undefined

考题二:

  1. console.log( typeof(NaN) );       //number
  2. console.log( typeof(null) );      //object

 四、null和undefined的区别

1. 作者在设计js的都是先设计的null(为什么设计了null:最初设计js的时候借鉴了java的语言)
2. null会被隐式转换成0,很不容易发现错误。
3. 先有null后有undefined,出来undefined是为了填补之前的坑。

具体区别:JavaScript的最初版本是这样区分的:null是一个表示"无"的对象(空对象指针),转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。

五、==和===有什么不同?  

==  :  比较的是值

        string == number || boolean || number ....都会隐式转换
        通过valueOf转换(valueOf() 方法通常由 JavaScript 在后台自动调用,并不显式地出现在代码中。)

=== : 除了比较值,还比较类型

六、JS微任务和宏任务

1. js是单线程的语言。
2. js代码执行流程:同步执行完==》事件循环
    同步的任务都执行完了,才会执行事件循环的内容
    进入事件循环:请求、定时器、事件....
3. 事件循环中包含:【微任务、宏任务】
微任务:promise.then
宏任务:setTimeout..

要执行宏任务的前提是清空了所有的微任务

流程:同步==》事件循环【微任务和宏任务】==》微任务==》宏任务=》微任务...

七、JS作用域考题

1. 除了函数外,js是没有块级作用域。
2. 作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量。
             注意:如果内部有,优先查找到内部,如果内部没有就查找外部的。
3. 注意声明变量是用var还是没有写(window.)
4. 注意:js有变量提升的机制【变量悬挂声明】
5. 优先级:声明变量 > 声明普通函数 > 参数 > 变量提升

 考题一:

  1. function c(){
  2.     var b = 1;
  3.     function a(){
  4.         console.log( b );
  5.         var b = 2;
  6.         console.log( b );
  7.     }
  8.     a();
  9.     console.log( b );
  10. }
  11. c();

考题二:

  1. var name = 'a';
  2. (function(){
  3.     if( typeof name == 'undefined' ){
  4.         var name = 'b';
  5.         console.log('111'+name);
  6.     }else{
  7.         console.log('222'+name);
  8.     }
  9. })()

考题三:

  1. function fun( a ){
  2.     var a = 10;
  3.     function a(){}
  4.     console.log( a );
  5. }
  6. fun( 100 );

八、JS对象考题

JS对象注意点:

1. 对象是通过new操作符构建出来的,所以对象之间不想等(除了引用外);
2. 对象注意:引用类型(共同一个地址);
3. 对象的key都是字符串类型;
4. 对象如何找属性|方法;
    查找规则:先在对象本身找 ===> 构造函数中找 ===> 对象原型中找 ===> 构造函数原型中找 ===> 对象上一层原型查找

考题一:

 [1,2,3] === [1,2,3]   //false

 考题二:

  1. var obj1 = {
  2. a:'hellow'
  3. }
  4. var obj2 = obj1;
  5. obj2.a = 'world';
  6. console.log(obj1); //{a:world}
  7. (function(){
  8. console.log(a); //undefined
  9. var a = 1;
  10. })();

考题三:

  1. var a = {}
  2. var b = {
  3. key:'a'
  4. }
  5. var c = {
  6. key:'c'
  7. }
  8. a[b] = '123';
  9. a[c] = '456';
  10. console.log( a[b] ); // 456

九、JS作用域+this指向+原型的考题

考题一:

  1. function Foo(){
  2. getName = function(){console.log(1)} //注意是全局的window.
  3. return this;
  4. }
  5. Foo.getName = function(){console.log(2)}
  6. Foo.prototype.getName = function(){console.log(3)}
  7. var getName = function(){console.log(4)}
  8. function getName(){
  9. console.log(5)
  10. }
  11. Foo.getName(); //2
  12. getName(); //4
  13. Foo().getName(); //1
  14. getName(); //1
  15. new Foo().getName();//3

考题二:

  1. var o = {
  2. a:10,
  3. b:{
  4. a:2,
  5. fn:function(){
  6. console.log( this.a ); // 2
  7. console.log( this ); //代表b对象
  8. }
  9. }
  10. }
  11. o.b.fn();

考题三:

  1. window.name = 'ByteDance';
  2. function A(){
  3. this.name = 123;
  4. }
  5. A.prototype.getA = function(){
  6. console.log( this );
  7. return this.name + 1;
  8. }
  9. let a = new A();
  10. let funcA = a.getA;
  11. funcA(); //this代表window

考题四:

  1. var length = 10;
  2. function fn(){
  3. return this.length + 1;
  4. }
  5. var obj = {
  6. length:5,
  7. test1:function(){
  8. return fn();
  9. }
  10. }
  11. obj.test2 = fn;
  12. console.log( obj.test1() ); //1
  13. console.log( fn()===obj.test2() ); //false
  14. console.log( obj.test1() == obj.test2() ); //false

十、JS判断变量是不是数组,你能写出哪些方法?

方式一:isArray

  1. var arr = [1,2,3];
  2. console.log( Array.isArray( arr ) );

方式二:instanceof 【可写,可不写】

  1. var arr = [1,2,3];
  2. console.log( arr instanceof Array );

方式三:原型prototype

  1. var arr = [1,2,3];
  2. console.log( Object.prototype.toString.call(arr).indexOf('Array') > -1 );

方式四:isPrototypeOf()

  1. var arr = [1,2,3];
  2. console.log( Array.prototype.isPrototypeOf(arr) )

方式五:constructor

  1. var arr = [1,2,3];
  2. console.log( arr.constructor.toString().indexOf('Array') > -1 )

十一、slice是干嘛的、splice是否会改变原数组

1. slice是来截取的

  • 参数可以写slice(3)、slice(1,3)、slice(-3)
  • 返回的是一个新的数组

2. splice 功能有:插入、删除、替换

  • 返回:删除的元素
  • 该方法会改变原数组

 十二、JS数组去重

方式一:new set

  1. var arr1 = [1,2,3,2,4,1];
  2. function unique(arr){
  3. return [...new Set(arr)]
  4. }
  5. console.log( unique(arr1) );

方式二:indexOf

  1. var arr2 = [1,2,3,2,4,1];
  2. function unique( arr ){
  3. var brr = [];
  4. for( var i=0;i<arr.length;i++){
  5. if( brr.indexOf(arr[i]) == -1 ){
  6. brr.push( arr[i] );
  7. }
  8. }
  9. return brr;
  10. }
  11. console.log( unique(arr2) );

方式三:sort

  1. var arr3 = [1,2,3,2,4,1];
  2. function unique( arr ){
  3. arr = arr.sort();
  4. var brr = [];
  5. for(var i=0;i<arr.length;i++){
  6. if( arr[i] !== arr[i-1]){
  7. brr.push( arr[i] );
  8. }
  9. }
  10. return brr;
  11. }
  12. console.log( unique(arr3) );

 十三、找出多维数组最大值

  1. function fnArr(arr){
  2. var newArr = [];
  3. arr.forEach((item,index)=>{
  4. newArr.push( Math.max(...item) )
  5. })
  6. return newArr;
  7. }
  8. console.log(fnArr([
  9. [4,5,1,3],
  10. [13,27,18,26],
  11. [32,35,37,39],
  12. [1000,1001,857,1]
  13. ]));

 十四、给字符串新增方法实现功能

给字符串对象定义一个addPrefix函数,当传入一个字符串str时,它会返回新的带有指定前缀的字符串,例如:

console.log( 'world'.addPrefix('hello') ) 控制台会输出helloworld

  1. String.prototype.addPrefix = function(str){
  2. return str + this;
  3. }
  4. console.log( 'world'.addPrefix('hello') )

 十五、找出字符串出现最多次数的字符以及次数

  1. var str = 'aaasdwqeasdaqwd';
  2. var o = {};
  3. for (var i = 0; i < str.length; i++) {
  4. var index = str[i];
  5. if (!o[index]) {
  6. o[index] = 1;
  7. } else {
  8. o[index]++;
  9. }
  10. }
  11. var max = 0;
  12. var str1 = '';
  13. for (var k in o) {
  14. if (o[k] > max) {
  15. max = o[k];
  16. str1 = k;
  17. }
  18. }
  19. console.log('出现最多的次数:' + max + '及其字母为:' + str1);

 十六、new操作符具体做了什么

  1. 在内存中创建一个新的空对象。
  2. 让 this 指向这个新的对象。
  3. 执行构造函数里面的代码,给这个新对象添加属性和方法
  4. 返回这个新对象(所以构造函数里面不需要return)

 十七、闭包

1. 闭包是什么
    闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量。

 优点:

  • 可以访问到函数内部的局部变量,
  • 可以避免全局变量的污染,
  • 这些变量的值始终保持在内存中,不会在外层函数调用后被自动清除(不会被垃圾回收)。

缺点:会增大内存使用量,滥用闭包会影响性能,导致内存泄漏【如果说一定要提到ie】等问题。

解决方法:在退出函数之前,将不使用的局部变量全部删除,可以使变量赋值为null。

2. 什么是垃圾?

  • 没有被引用的对象或变量
  • 无法访问到的对象

垃圾回收机制:

执行环境负责管理代码执行过程中使用的内存。JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,没有被释放,导致该内存无法被使用,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。

 十八、原型链

1. 原型可以解决什么问题

  •     对象共享属性和共享方法

2. 谁有原型

  • 函数拥有:prototype
  • 对象拥有:__proto__

3. 对象查找属性或者方法的顺序

  • 先在对象本身查找 --> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找

4. 原型链
    4.1 是什么?:就是把原型串联起来
    4.2 原型链的最顶端是null

 十九、JS继承有哪些方式

方式一:ES6

  1. class Parent{
  2. constructor(){
  3. this.age = 18;
  4. }
  5. }
  6. class Child extends Parent{
  7. constructor(){
  8. super();
  9. this.name = '张三';
  10. }
  11. }
  12. let o1 = new Child();
  13. console.log( o1,o1.name,o1.age );

方式二:原型链继承

  1. function Parent(){
  2. this.age = 20;
  3. }
  4. function Child(){
  5. this.name = '张三'
  6. }
  7. Child.prototype = new Parent();
  8. let o2 = new Child();
  9. console.log( o2,o2.name,o2.age );

方式三:借用构造函数继承

  1. function Parent(){
  2. this.age = 22;
  3. }
  4. function Child(){
  5. this.name = '张三'
  6. Parent.call(this);
  7. }
  8. let o3 = new Child();
  9. console.log( o3,o3.name,o3.age );

方式四:组合式继承

  1. function Parent(){
  2. this.age = 100;
  3. }
  4. function Child(){
  5. Parent.call(this);
  6. this.name = '张三'
  7. }
  8. Child.prototype = new Parent();
  9. let o4 = new Child();
  10. console.log( o4,o4.name,o4.age );

 二十、call、apply、bind区别

共同点:功能一致

可以改变this指向

语法: 函数.call()、函数.apply()、函数.bind()

区别:

  • 1. call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入()执行。
  • 2. 参数不同:apply第二个参数是数组。call和bind有多个参数需要挨个写。

场景:

  1. 1. 用apply的情况
  2. var arr1 = [1,2,4,5,7,3,321];
  3. console.log( Math.max.apply(null,arr1) )
  4. 2. 用bind的情况
  5. var btn = document.getElementById('btn');
  6. var h1s = document.getElementById('h1s');
  7. btn.onclick = function(){
  8. console.log( this.id );
  9. }.bind(h1s)

 二十一、sort背后原理是什么?

V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 InsertionSort,比10大的数组则使用 QuickSort。

之前的版本是:插入排序和快排,现在是冒泡

原理实现链接:https://github.com/v8/v8/blob/ad82a40509c5b5b4680d4299c8f08d6c6d31af3c/src/js/array.js

***710行代码开始***

二十二、深拷贝和浅拷贝

共同点:复制
 

1. 浅拷贝:只复制引用,而未复制真正的值。

  1. var arr1 = ['a','b','c','d'];
  2. var arr2 = arr1;
  3. var obj1 = {a:1,b:2}
  4. var obj2 = Object.assign(obj1);

2. 深拷贝:是复制真正的值 (不同引用)

  1. var obj3 = {
  2. a:1,
  3. b:2
  4. }
  5. var obj4 = JSON.parse(JSON.stringify( obj3 ));

//递归的形式

  1. var oldObj = {
  2. a: 1,
  3. b: 2,
  4. arr: ['1', '2', '3']
  5. };
  6. var newObj = {};
  7. function recursion(newObj, oldObj) {
  8. for (var k in oldObj) {
  9. var item = oldObj[k];
  10. if (item instanceof Array) {
  11. newObj[k] = [];
  12. recursion(newObj[k], item);
  13. } else if (item instanceof Object) {
  14. newObj[k] = {};
  15. recursion(newObj[k], item);
  16. } else {
  17. newObj[k] = item;
  18. }
  19. }
  20. return newObj;
  21. }
  22. recursion(newObj, oldObj);
  23. newObj.a = '我是你爸爸真伟大'
  24. console.log(newObj);
  25. console.log(oldObj);

二十三、localStorage、sessionStorage、cookie的区别

公共点:在客户端存放数据

区别:

1. 数据存放有效期

  • sessionStorage : 仅在当前浏览器窗口关闭之前有效。【关闭浏览器就没了】
  • localStorage      : 始终有效,窗口或者浏览器关闭也一直保存,所以叫持久化存储。
  • cookie                : 只在设置的cookie过期时间之前有效,即使窗口或者浏览器关闭也有效。

2. localStorage、sessionStorage不可以设置过期时间

  • cookie 有过期时间,可以设置过期(把时间调整到之前的时间,就过期了)

3. 存储大小的限制

  • cookie存储量不能超过4k
  • localStorage、sessionStorage不能超过5M

        ****根据不同的浏览器存储的大小是不同的。

二十四、http状态码的了解

  • 2开头的表示请求成功
    • 200表示一切正常
  • 3开头的表示重定向
    • 301永久重定向
    • 302临时重定向
  • 4开头表示客户端错误
    • 400表示请求报文中存在语法错误
    • 403常见的跨域
    • 404请求资源不存在
  • 5开头表示服务器端错误
    • 500表明服务器端在执行请求时发生了错误

二十五、防抖和节流的作用

共同点:限制函数的执行次数

防抖:通过setTimeout的方式,在一定的时间间隔内,将多次触发只执行最后一次触发;
节流:减少一段时间的触发频率

 二十六、var、let、const区别

var、let、const 共同点都是可以声明变量的

区别一:

  •     var 具有变量提升的机制
  •     let和const没有变量提升的机制

区别二:

  •     var 可以多次声明同一个变量
  •     let和const不可以多次声明同一个变量

区别三:

  •     var、let声明变量的
  •     const声明常量
  •     var和let声明的变量可以再次赋值,但是const不可以再次赋值了。

区别四:

  •     var声明的变量没有自身作用域
  •     let和const声明的变量有自身的作用域

 二十七、作用域考题

考题一:let和const没有变量提升性

  1. console.log( str );//undefined
  2. var str = '你好';
  3. console.log( num );//报错
  4. let num = 10;

考题二:

  1. function demo(){
  2. var n = 2;
  3. if( true ){
  4. var n = 1;
  5. }
  6. console.log( n );//1
  7. }
  8. demo();
  9. function demo(){
  10. let n = 2;
  11. if( true ){
  12. let n = 1;
  13. }
  14. console.log( n );//2
  15. }
  16. demo();

考题三:可以修改

  1. const obj = {
  2. a:1
  3. }
  4. obj.a = 11111;
  5. console.log( obj )
  6. const arr = ['a','b','c'];
  7. arr[0]= 'aaaaa';
  8. console.log( arr );

 二十八、将下列对象进行合并

方式一:Object.assign

  1. const a = {a:1,b:4};
  2. const b = {b:2,c:3};
  3. let obj1 = Object.assign(a,b);
  4. console.log( obj1 );

方式二:...

  1. let obj2 = {...a,...b};
  2. console.log( obj2 );

方式三:自己封装方法

  1. function extend( target, source ){
  2. for(var key in source){
  3. target[key] = source[key];
  4. }
  5. return target;
  6. }
  7. console.log( extend(a,b) );

 二十九、箭头函数和普通函数有什么区别?

1. this指向的问题

  • 箭头函数中的this只在箭头函数定义时就决定的,而且不可修改的(call、apply、bind)
  • ****箭头函数的this指向定义时候、外层第一个普通函数的this

2. 箭头函数不能new(不能当作构造函数)
3. 箭头函数prototype
4. 箭头函数arguments

 三十、Promise有几种状态

有三种状态:

  • pending(进行中)
  • fulfilled(已成功)
  • rejected(已失败)

Promise 是es6引入的异步编程解决方案

 可以链式调用,解决回调地狱的问题

 三十一、find和filter的区别  

区别一:返回的内容不同

  • filter  返回是新数组
  • find   返回具体的内容

区别二:

  • find    匹配到第一个即返回
  • filter   返回整体(没一个匹配到的都返回) 

 三十二、some和every的区别  

  • some    如果有一项匹配则返回true
  • every    全部匹配才会返回true

 三十三、利用递归求斐波那契数列

  1. function fb(n) {
  2. if (n == 0) {
  3. return 0;
  4. }
  5. if (n <= 2) {
  6. return 1;
  7. }
  8. return fb(n - 1) + fb(n - 2);
  9. }
  10. console.log(fb(9));

 三十四、利用递归求阶乘

  1. function fn(n) {
  2. if (n == 1) {
  3. return 1;
  4. }
  5. return n * fn(n - 1);
  6. }
  7. console.log(fn(3));

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/339911
推荐阅读
相关标签
  

闽ICP备14008679号