JavaScript相关面试题2:1.深拷贝和浅拷贝区别;2. [“1“,“2“,“3“].map(parselInt)的返回值;3.预防按钮的重复点击

简介: 解决方案1.控制按钮,在短时间内被多次点击,第一次以后的点击无效。2.控制按钮,在点击按钮触发的请求响应之前,再次点击无效。3.配置特殊的URL,然后控制这些URL请求的最小时间间隔。如果再次请求跟前一-次请求间隔很小,弹窗二次提示,是否继续操作。防止无意识复点击按钮给按钮添加控制,在control 毫秒内,第一次点击事件之后的点击事件不执行。

文章目录

深拷贝浅拷贝有什么区别?怎么实现深拷贝?

["1","2","3"].map(parselInt)的返回值是什么?

怎么预防按钮的重复点击?

深拷贝浅拷贝有什么区别?怎么实现深拷贝?

浅拷贝

浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝

如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址

即浅拷贝是拷贝一层,深层次的引用类型则共享内存地址

下面简单实现一个浅拷贝


function shallowClone(obj) {

   const newObj = {};

   for(let prop in obj) {

       if(obj.hasOwnProperty(prop)){

           newObj[prop] = obj[prop];

       }

   }

   return newObj;

}

1

2

3

4

5

6

7

8

9

在JavaScript中,存在浅拷贝的现象有:

Object.assign

Array.prototype.slice(), Array.prototype.concat()

使用拓展运算符实现的复制


深拷贝

深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

常见的深拷贝方式有:

_.cloneDeep()

jQuery.extend()

JSON.stringify()

手写循环递归


_.cloneDeep()


const _ = require('lodash');

const obj1 = {

   a: 1,

   b: { f: { g: 1 } },

   c: [1, 2, 3]

};

const obj2 = _.cloneDeep(obj1);

console.log(obj1.b.f === obj2.b.f);// false

1

2

3

4

5

6

7

8

jQuery.extend()


const $ = require('jquery');

const obj1 = {

   a: 1,

   b: { f: { g: 1 } },

   c: [1, 2, 3]

};

const obj2 = $.extend(true, {}, obj1);

console.log(obj1.b.f === obj2.b.f); // false

1

2

3

4

5

6

7

8

JSON.stringify()


const obj2=JSON.parse(JSON.stringify(obj1));


1

2

循环递归


function deepClone(obj, hash = new WeakMap()) {

 if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作

 if (obj instanceof Date) return new Date(obj);

 if (obj instanceof RegExp) return new RegExp(obj);

 // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝

 if (typeof obj !== "object") return obj;

 // 是对象的话就要进行深拷贝

 if (hash.get(obj)) return hash.get(obj);

 let cloneObj = new obj.constructor();

 // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身

 hash.set(obj, cloneObj);

 for (let key in obj) {

   if (obj.hasOwnProperty(key)) {

     // 实现一个递归拷贝

     cloneObj[key] = deepClone(obj[key], hash);

   }

 }

 return cloneObj;

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

区别



从上图发现,浅拷贝和深拷贝都创建出一个新的对象,但在复制对象属性的时候,行为就不一样

浅拷贝只复制属性指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改对象属性会影响原对象


[“1”,“2”,“3”].map(parselInt)的返回值是什么?

首先整个题目考校的是两个函数,和一个字符串转数字的概念

1.数组的map函数,接受三个参数,当前值,当前索引,当前数组。

2. parselnt接受两个参数,需要转换的字符串,基数(基数取值范围2~36)

3. 根据上面的两个函数的解释,我们可以发现实际上,上面的[‘1’,‘2’,‘3’].map(parseInt) 其实就是等价于下面的代码。


['1','2','3'].map((item, index) => {  

   return parseInt(item, index)  

})  

//  parseInt('1', 0)  1  

//  parseInt('2', 1)  NaN  

//  parseInt('3', 2)  NaN

1

2

3

4

5

6

4.如果我们需要返回1,2,3需要怎么办?


function parseIntFun(item) {  

   return parseInt(item, 10)  

}  

['1','2','3'].map(parseIntFun)  

//  parseInt('1', 10)  1  

//  parseInt('2', 10)  2  

//  parseInt('3', 10)  3

1

2

3

4

5

6

7

怎么预防按钮的重复点击?

先看看在那些场景会导致重复请求:

1.手速快,不小心双击操作按钮。

2.很小心的点击了一次按钮,因为请求响应比较慢,页面没有任何提示,怀疑上次点击没生效,再次点击操作按钮。

3.很小心的点击了一次按钮, 因为请求响应比较慢,页面没有任何提示,刷新页面,再次点击操作按钮。


解决方案

1.控制按钮,在短时间内被多次点击,第一次以后的点击无效。

2.控制按钮,在点击按钮触发的请求响应之前,再次点击无效。

3.配置特殊的URL,然后控制这些URL请求的最小时间间隔。如果再次请求跟前一-次请求间隔很小,弹窗二次提示,是否继续操作。


防止无意识复点击按钮

给按钮添加控制,在control 毫秒内,第一次点击事件之后的点击事件不执行。


<template>

   <button @click="handleClick"></button>

</templage>

<script>

export default {

   methods: {

       handleClick(event) {

           if (this.disabled) return;

           if (this.notAllowed) return;

           // 点击完多少秒不能继续点

           this.notAllowed = true;

           setTimeout(()=>{

               this.notAllowed = false;

           }, this.control)

           this.$emit('click', event, this);

       }

   }

}

</script>


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

按钮点击立马禁用,等响应回来才能继续点击

触发点击的button实例传入fetch配置,代码如下:


doQuery: function (button) {

   this.FesApi.fetch(`generalcard/query`, {

       sub_card_type: this.query.sub_card_type,

       code_type: this.query.code_type,

       title: this.query.title,

       card_id: this.query.card_id,

       page_info: {

           pageSize: this.paginationOption.page_info.pageSize,

           currentPage: this.paginationOption.page_info.currentPage

       }

   }, {

       //看这里,加上下面一行代码就行。。so easy

       button: button

   }).then(rst => {

       // 成功处理

   });

}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

在fetch函数内部,设置button的disabled=true,当响应回来时,设置disabled=false代码如下:


const action = function (url, data, option) {

   // 如果传了button

   if (option.button) {

       option.button.currentDisabled = true;

   }

   // 记录日志

   const log = requsetLog.creatLog(url, data);


   return param(url, data, option)

       .then(success, fail)

       .then((response) => {

           requsetLog.changeLogStatus(log, 'success');

           if (option && option.button) {

               option.button.currentDisabled = false;

           }

           return response;

       })

       .catch((error) => {

           requsetLog.changeLogStatus(log, 'fail');

           if (option && option.button) {

               option.button.currentDisabled = false;

           }

           error.message && window.Toast.error(error.message);

           throw error;

       });

};


目录
相关文章
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
764 1
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
480 0
|
JavaScript 前端开发 容器
this、self、window、top 在 JavaScript 中的区别深入研究
在 JavaScript 开发中,`this`、`self`、`window` 和 `top` 是四个常用的概念。`this` 指向当前执行上下文的对象,其值取决于函数调用方式;`self` 在全局作用域中等同于 `window`,常用于 Web Workers;`window` 代表浏览器窗口,是全局变量的容器;`top` 指向最顶层窗口,用于判断是否在框架中。理解这些概念有助于编写健壮的代码。
584 1
this、self、window、top 在 JavaScript 中的区别深入研究
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
JavaScript 前端开发 开发者
flat、flatmap与map的用法区别
本文介绍了 JavaScript 数组方法 `flat()`、`flatMap()` 和 `map()` 的用法及区别。`flat()` 可按指定深度递归展平数组,参数为深度,默认一层;`flatMap()` 结合了 `map()` 和 `flat()` 功能,返回一维数组,长度可能不同于原数组;而 `map()` 返回与原数组长度一致的新数组。通过多个代码示例展示了三者的功能和差异,帮助开发者更好地理解和使用这些方法。
1674 0
|
移动开发 运维 供应链
通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
array.some()可以用来权限检查、表单验证、库存管理、内容审查和数据处理等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
供应链 JavaScript 前端开发
通过array.every()实现数据验证、权限检查和一致性检查;js数组元素检查的方法,every()的使用详解,array.some与array.every的区别(附实际应用代码)
array.every()可以用来数据验证、权限检查、一致性检查等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
722 1
|
设计模式 JavaScript 前端开发
js中new和object.creat区别
【10月更文挑战第29天】`new` 关键字和 `Object.create()` 方法在创建对象的方式、原型链继承、属性初始化以及适用场景等方面都存在差异。在实际开发中,需要根据具体的需求和设计模式来选择合适的方法来创建对象。