JavaScript考试题(一)

简介: JavaScript考试题(一)

一.数组扁平化


(将一个多维数组变为一个一维数组。例如,将数组[1, 2, [3, [4, 5]], [6, 7]]扁平化处理后输出[1, 2, 3, 4, 5, 6, 7];)


 function getArray(arr) {
        let res = [];
        for (let i = 0; i < arr.length; i++) {
            if (Array.isArray(arr[i])) {
                res = res.concat(getArray(arr[i]));
            } else {
                res.push(arr[i]);
            }
        }
        return res;
    }
    console.log(getArray([1, 2, [3, [4, 5]], [6, 7]]));//[1, 2, 3, 4, 5, 6, 7]


二.合并有序数组


给定两个从小到大排好序的数组,亲,请你把它两个合并成新的数组,合并后的结果依然有序。如:给定数组:[1,3,7,15,20]和数组:[-5,0,2,8,9,12]。那么结果是:[-5,0,1,2,3,7,8,9,12,15,20]


  function mergeSortedArrays(arr1, arr2) {
        var mergedArray = arr1.concat(arr2);
        return mergedArray.sort(function (a, b) {
            return a - b;
        });
    }
    var arr1 = [1, 3, 7, 11111,312323,313215, 20, 232132331];
    var arr2 = [-5, 0, 2, 8, 9, 12,111];
    var mergedArray = mergeSortedArrays(arr1, arr2);
    console.log(mergedArray); // [-5, 0, 1, 2, 3, 7, 8, 9, 12, 15, 20]
 let arr = [1, 2, 3]
    let arr1 = [3, 7, 5]
    let arr2 = [...arr, ...arr1]
    arr.sort((a, b) => a - b)
    console.log(arr2);


三.求两个数的交集


如:给定数组 [12,23,34,45]和数组 [21,23,45,100],那么交集是[23,34];


function intersection(arr1, arr2) {
        var set1 = new Set(arr1);
        var set2 = new Set(arr2);
        var result = new Set();
        for (var value of set1) {
            if (set2.has(value)) {
                result.add(value);
            }
        }
        return Array.from(result);
    }
    var arr1 = [12, 23, 34, 45,21];
    var arr2 = [21, 23, 45, 100];
    var result = intersection(arr1, arr2);
    console.log(result); // [23, 45]


四.最接近三个数之和


给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在恰好一个解。


function threeSumClosest(nums, target) {
        let closestSum = nums[0] + nums[1] + nums[2]; // 初始化最接近的三数之和
        for (let i = 0; i < nums.length - 2; i++) {
            for (let j = i + 1; j < nums.length - 1; j++) {
                for (let k = j + 1; k < nums.length; k++) {
                    const sum = nums[i] + nums[j] + nums[k];
                    if (Math.abs(sum - target) < Math.abs(closestSum - target)) { // 如果当前的三数之和更接近目标值,则更新最接近的三数之和
                        closestSum = sum;
                    }
                }
            }
        }
        return closestSum;
    }
    console.log(threeSumClosest([1, 2, 3, 4, 5], 7))


五.实现事件处理器EventEmitter,有如下功能


       const event = new EventEmitter();

       绑定事件

       event.on(name, callback);

       取消绑定

       event.off(name);

       触发事件

       event.emit(name, data);


// 自己实现一个事件处理机制:(事件绑定,事件触发,事件解绑);

 

class EventEmitter {
        constructor() {
            this.events = {};
        }
        // 绑定事件:
        // 参数:
        //    name:事件名
        //    callback:事件处理函数
        on(name, callback) {
            this.events[name] = callback;
        }
        // 触发事件
        //   name:事件名
        //   data:传给事件处理函数的参数
        emit(name, data) {
            this.events[name](data);
        }
        // 解绑事件:
        // 参数:
        //   name:事件名
        off(name) {
            delete this.events[name];
        }
    }
    const event = new EventEmitter();
    // 绑定事件
    event.on("myclick", function (params) {
        console.log("myclick", params);
    });
    event.on("yourclick", function (params) {
        console.log("yourclick", params);
    });
    function fn01() {
        // 触发事件
        event.emit("myclick", "hi");
    }
    function fn02() {
        event.emit("yourclick", "hello");
    }
    function fn03() {
        // 取消绑定
        event.off("myclick");
    }


六.请阅读如下代码(非严格模式下),写出结果,并写出为什么?


  var a = 2;
    const foo = {
        bar: function () {
            console.log(this.a,"20");
        },
        bar1: function () {
            return function () {
                console.log(this.a,"24");
            }
        },
        a: 1
    }; 
    foo.bar();//1
    var bar1 = foo.bar1();
    console.log(bar1,"31")
    bar1();//2  
  // foo.bar() 方法是直接通过 foo 对象调用的,所以其中的 this 指向的是 foo 对象本身,而 foo 对象中的 a 属性的值为 1,所以输出结果为 1。
    // 而执行 bar1() 方法时,实际上是通过 return 返回的函数执行的,因此其执行上下文中的 this 指向的是全局对象 window(或者在某些环境中是 global 对象),而全局对象中定义的 a 变量的值为 2,所以输出结果为 2。


七.请编写函数,将data数组中所有对象按照value从小到大排列,不能使用sort函数。


     var data = [{
             name: "uc",
             value: 5
         }, {
             name: "amap",
             value: 2
         }, {
             name: "ali",
             value: 3
         }
       ]
function bubbleSort(arr, compareFn) {
        for (var i = 0; i < arr.length; i++) {
            for (var j = 0; j < arr.length - 1 - i; j++) {
                if (compareFn(arr[j], arr[j + 1]) > 0) {
                    [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
                }
            }
        }
        return arr;
    }
    function compareByValue(a, b) {
        return a.value - b.value;
    }
    console.log(bubbleSort(data, compareByValue))


七.封装一个queryString函数,支持输入 URL来获取 query 等参数)


例如,输入https://www.antgroup.com?

name=ant&from=alibaba&job-frontend&extraInfo %7B%22a%22%3A%226%22%2C%22C%22%3A%22d%22%7D


可得到一个这样的对象

(name:"ant",from: "alibaba' ,job: "frontend" ,extraInfo: (a:"b', c:'d]}本平台可运行代码,建议在平台跑通后再提交

 function getURLParams(url) {
        const [fullURL, queryString] = url.split('?'); // 将 URL 分割成 URL 本身和查询字符串两部分
        const query = new URLSearchParams(queryString); // 使用 URLSearchParams 解析查询字符串
        const result = {}; // 初始化结果对象
        for (const [key, value] of query) { // 遍历解析后的查询字符串
            if (/\[\]$/.test(key)) { // 如果键以 [] 结尾,说明这是一个数组
                const name = key.slice(0, -2); // 去掉 [] 后缀,得到数组名
                if (result[name]) { // 如果结果对象已经有了这个数组
                    result[name].push(parseParamValue(value)); // 在数组中添加新的值
                } else {
                    result[name] = [parseParamValue(value)]; // 否则创建一个新的数组
                }
            } else { // 否则这是一个普通的键值对
                result[key] = parseParamValue(value); // 直接将值添加到结果对象中
            }
        }
        // return { url: fullURL, query: result }; // 返回 URL 和解析后的查询参数对象
        return result
    }
    function parseParamValue(value) { // 解析参数的值
        try { // 尝试解析 JSON
            return JSON.parse(value);
        } catch { // 如果失败则返回原始字符串
            return value;
        }
    }
    const url =
        "https://example.com/path?param1=value1&param2=[1,2,3]&param3=%7B%22key%22%3A%22value%22%7D&param4=not%20a%20JSON";
    const params = getURLParams(url); // 获取解析后的查询参数对象
    console.log(params); // 输出查询参数对象


八. 用递归实现:求两个数的最大公约数(思路:使用欧几里得算法)。要求封装成函数。


   //     首先确定如何求最大公约数,我们采用欧几里得算法(辗转相除法),算法描述如下:
    //     例:48, 57
    //     57 % 48=9     大数对小数求余
    //     48 % 9=3       小数对上次的余数求余,重复这个过程直到余数为0
    //     9 % 3=0            余数为0时,此次求余的小数就是最大公约数
    //     第一次运算n1 = 57, n2 = 48, n3 = 9,第二次运算n1 = 48, n2 = 9, n3 = 3, 第三次运 
    //     算n1 = 9, n2 = 3, n3 = 0
    //     规律是:求余的大数是前次运算的小数,小数是前次运算的余数,余数是0就结束。
 function gongYS(n1, n2) {
        let n3 = n1 % n2;
        n1 = n2;
        n2 = n3;
        if (n3 == 0) {
            return n1;
        }
        return gongYS(n1, n2);
    }
    console.log(gongYS(48, 57));


 九.利用递归求两个数的最大公约数

 

  function gongYS(m, n) {//最大公约数函数
    var r = 0;//声明变量r;
        r = m % n;//把m%n的值赋值给r;
         m = n;//把n的值给m;
        n = r;//把r的值给n;
         if (r == 0) {//如果r等于0,说明最大公约数是那个值小的数,比如:16/8;
            return m;//n的值赋值给m后,返回值为m;
        }
        return gongYS(m, n);//否则继续运行函数
     }
     var result = gongYS(16, 24);
     console.log(result);


 十.把下面的对象数组变成对象嵌套。


   规则:每个对象的parentId就是父级对象的id。


  // let arr = [
    //     {
    //         id: 1,
    //         name: "张一",
    //         parentId: null
    //     },
    //     {
    //         id: 2,
    //         name: "张二",
    //         parentId: 1
    //     },
    //     {
    //         id: 3,
    //         name: "张三",
    //         parentId: 1
    //     },
    //     {
    //         id: 4,
    //         name: "张四",
    //         parentId: 2
    //     },
    //     {
    //         id: 5,
    //         name: "张五",
    //         parentId: 2
    //     },
    //     {
    //         id: 6,
    //         name: "张六",
    //         parentId: 3
    //     },
    //     {
    //         id: 7,
    //         name: "张七",
    //         parentId: 4
    //     },
    //     {
    //         id: 8,
    //         name: "张八",
    //         parentId: 6
    //     }
    // ]
    //方法一:======================================================================
 function arrToJson(root) {
        // 2、循环数组,找子元素
        let children = arr.filter(item => item.parentId == root.id);
        if (children.length > 0) {
            root.children = children;
            children.forEach(item => {
                arrToJson(item);
            })
        };
    }
    // 1、先找的根元素;
    let root = arr.filter(item => item.parentId == null)[0]
    arrToJson(root);
    console.log(root);
    //方法二:======================================================================
 function arrToJSON(arr) {
        let root;
        arr.forEach(item => {        
            if(item.parentId!=null){
                // 如果有父级
                // 找到父级
                let parentObj = arr.filter(parentItem=>parentItem.id===item.parentId)[0];
                // 给父级增加children属性(数组)
                !parentObj.children && (parentObj.children=[]);
                // 把自己添加到父级的children属性(数组)
                parentObj.children.push(item);
            }else{
                root = item;
            }
        });
        return root;
    }
    console.log(arrToJSON(arr));
    console.log(arr.length);


十一.封装一个函数,完成功能:add(2).multi(9).div(3) 的结果是6。


function add(x) {
  return {
    multi(y) {
      return {
        div(z) {
          return x*y/z;
        }
      }
    }
  };
}
console.log(add(2).multi(9).div(3)); // 输出6
console.log(['1', '2', '3'].map(parseInt))



十二. ['1', '2', '3'].map(parseInt)的结果是什么 ? 为什么 ?

 

console.log(['1', '2', '3'].map(parseInt));//[1, NaN, NaN];
    // 这是因为 map 函数会将数组中的每一个元素都调用一遍指定的函数,
    // 并将函数的返回值组成一个新的数组返回。parseInt 函数的第二个参数表示进制,
    // map 函数会将当前元素的值和索引分别作为 parseInt 函数的第一个和第二个参数传入。
    parseInt('1', 0); // 1
    parseInt('2', 1); // NaN,因为 '2' 不是一进制的数
    parseInt('3', 2); // NaN,因为 '3' 不是二进制的数


十三..请用两种方式完成数组去重


方式一
    function norepeat(arr){
      var newarr = [];
      for(var i = 0;i<arr.length;i++){
          if(newarr.indexof(arr[i]) == -1){
             newarr.push(arr[i])
          }
      }
      return newarr;
}
方式二
     function norepeat(arr){
       var newarr = arr; 
       var obj = {};
       for(var i = 0;i<arr.length;i++){
          obj[arr[i]] = 1;
       }
       return Object.keys(obj).map(item=>Number(item));
     }
方式三
     function norepeat(arr){
      var newarr = arr;
       newarr.sort();
       for(var i = 0;i<newarr.length;i++){
          if(arr[i] == arr[i+1]){
             arr.splice(i,1)
             i--;
          }
       }
       return newarr;
     }
方式四
     function norepeat(arr){
        return Array.from(new Set(arr));
     }


十四.  请写出常见的http状态码与含义(4中以上)


200:(成功)服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。
400:(错误请求)服务器不理解请求的语法
401:(未授权)请求要求身份验证。对于需要登录的网页,服务器可能返回此响应
403:(禁止)服务器拒绝请求
404:(未找到)服务器找不到请求的网页
408:(请求超时)服务器等候请求时发生超时
500:(服务器内部错误)服务器遇到错误,无法完成请求
502:(错误网关)服务器作为网关或代理,从上游服务器收到无效响应
503:(服务不可用)服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态
504:(网关超时)服务器作为网关或代理,但是没有及时从上游服务器收到请求
505:(HTTP 版本不受支持)服务器不支持请求中所用的 HTTP 协议版本


十五 . 如何解决跨域 并说出ajax与解决跨域方式的区别


①解决跨域三种方案:jsonp、cors、proxy
② AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。(注意!ajax不是跨域方式!它是一种技术)
请问jsonp是不是ajax中实现跨域访问的技术
​ jsonp不是AJAX中实现跨域访问的技术 ​ 1、jsonp没有使用XMLHttpRequest对象。 ​ 2、jsonp只是在一种跨域的技巧。 ​ 3、jsonp只支持Get方式;由于按照jsonp的这种方式跨域访问时,就是可以利用javascript和服务器端交互,能达到AJAX中XMLHttpRequest对象同样的效果
相关文章
|
7月前
|
监控 Linux Shell
常用的34个Linux Shell脚本,一定能帮到你(下)
常用的34个Linux Shell脚本,一定能帮到你(下)
158 1
|
7月前
|
缓存 运维 Linux
Linux(CentOS)运维脚本工具集合
Linux(CentOS)运维脚本工具集合
148 2
|
7月前
克隆yum源
克隆yum源
102 0
|
前端开发 JavaScript
学习JavaScript笔记
学习JavaScript笔记
63 0
|
7月前
|
分布式计算 DataWorks 数据可视化
DataWorks增强分析发布,一站式数据查询分析与可视化
8月31日阿里云郑州峰会,阿里云行业解决方案研发部总经理曾震宇在主论坛飞天发布时刻重磅发布DataWorks与DataV-Card合作推出的AI增强分析产品,一站式完成从数据查询、分析、可视化、共享的完整链路,1分钟即可形成数据报告,帮助互联网、金融、政务等各个行业客户表达数据观点,讲好数据故事。
1031 1
|
7月前
|
运维 监控 关系型数据库
Shell编程及自动化运维实现
Shell编程及自动化运维实现
|
7月前
|
关系型数据库 MySQL 应用服务中间件
Nginx__高级进阶篇之LNMP动态网站环境部署
Nginx__高级进阶篇之LNMP动态网站环境部署
101 0
|
7月前
|
SQL 缓存 关系型数据库
开源数据库Mysql_DBA运维实战 (总结)
开源数据库Mysql_DBA运维实战 (总结)
|
7月前
|
存储 运维 关系型数据库
开源数据库Mysql_DBA运维实战 (备份与还原)
开源数据库Mysql_DBA运维实战 (备份与还原)
|
7月前
|
存储 网络安全 数据安全/隐私保护
部署ZFile在线网盘
部署ZFile在线网盘
117 0