js(面试题) 小灰灰 2022-05-29 02:38 163阅读 0赞 shuffle:顾名思义,将数组随机排序,常在开发中用作实现随机功能。 我们来看看一个 shuffle 可以体现出什么*代码品味*。 ## 错误举例 ## function shuffle(arr) { arr.sort(function () { return Math.random() - 0.5; }); } // ES6 const shuffle = (arr) => { arr.sort(() => Math.random() - 0.5); } 请老铁千万不要这样写,这体现了两个错误: 1. 你的这段代码一定是从网上抄/背下来的,面试官不想考这种能力 2. 很遗憾,这是错误的,并不能真正地随机打乱数组。 Why? Check:https://blog.oldj.net/2017/01/23/shuffle-an-array-in-javascript/comment-page-1/\#comment-1466 ## 思考 ## 下面来到了第一反应:思考问题。 数组随机化 -> 要用到 `Math.random` \-> 看来每个元素都要 random 一下 -> 处理 `arr.length` 要用到 `Math.floor` \-> 需要用到 `swap` ## 第一版 ## 由此有了第一版代码: function shuffle(arr) { var i; var randomIndex; for (i = arr.length; i > 0; i--) { randomIndex = Math.random() * i; swap(arr, i, randomIndex); } } * 为什么用 randomIndex 不用 j? -> 更有意义的变量命名 * 为什么要把 i 和 randomIndex 的声明放在最前方? -> ES5 里的*变量提升*(ES6 里有没有变量提升?没有,不仅 `const` 和 `let` 都没有,连 `class` 也没有) * 为什么第 3 行和第 5 行中留一个空格?将声明的变量和函数体分开,*一目了然的逻辑*,*使代码更加清晰易维护* 什么,JavaScript 中木有 `swap` 函数? 写一个,使逻辑更加清晰 & 重复利用: function swap(arr, indexA, indexB) { var temp; temp = arr[indexA]; arr[indexA] = arr[indexB]; arr[indexB] = temp; } ## 第二版 ## 一点点小的改动: function shuffle(arr) { arr.forEach(function (curValue, index) { var randomIndex = Math.random() * index; swap(arr, index, randomIndex); }); } 用 `arr.forEach` 替代原本的 `for` 循环。 不希望有人质疑:JS 由于函数调用栈空间有限,用 `for` 循环不是比 `forEach` 效率更高吗? 拿出这段话压压惊: > ”We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.”-- Donald Knuth JavaScript 天生支持函数式编程(functional programing),放下脑海中的 CPP-OOP,请好好珍惜它。 有了 High-order function & First-class function 的存在,编写代码的*逻辑愈发清晰*,*简洁好维护*。 ## 第三版 ## 且慢,同学不写一个 ES6 版本的吗? const shuffle = arr => { arr.forEach((element, index) => { const randomIndex = Math.floor(Math.random() * (index + 1)) swap(arr, index, randomIndex) }) } 使用 ES6 的箭头函数(arrow function),逻辑的表达更为*简洁*、*清晰*、*好维护*。(我会告诉你箭头函数还因为本身绑定的是外部的 `this`,解决了一部分 `this` 绑定的问题嘛。注意我没有说*全部*)。 ## 进阶 ## 何不用 ES6 重写一下 `swap` 函数? const swap = (arr, indexA, indexB) => { [arr[indexA], arr[indexB]] = [arr[indexB], arr[indexA]] } 怎么样,ES6 的对象解构赋值(Destructuring)燃不燃?好用不好用? 但如果单独写一个 `swap` 函数,这样写没毛病,如果 `shuffle` 和 `swap` 一起写呢: const shuffle = arr => { arr.forEach((element, index) => { const randomIndex = Math.floor(Math.random() * (index + 1)) swap(arr, index, randomIndex) }) } const swap = (arr, indexA, indexB) => { [arr[indexA], arr[indexB]] = [arr[indexB], arr[indexA]] } 出现调用错误,`const` 声明的变量*没有变量提升*,在 `shuffle` 调用 `swap` 的时候 `swap` 还木有出生呢~! So 这样? const swap = (arr, indexA, indexB) => { [arr[indexA], arr[indexB]] = [arr[indexB], arr[indexA]] } const shuffle = arr => { arr.forEach((element, index) => { const randomIndex = Math.floor(Math.random() * (index + 1)) swap(arr, index, randomIndex) }) } 老铁没毛病。但主要逻辑 `shuffle` 放在后,次要逻辑 `swap` 放在前有没有不妥? ## 最终解答 ## function shuffle(arr) { arr.forEach((element, index) => { const randomIndex = Math.floor(Math.random() * (index + 1)) swap(arr, index, randomIndex) }) } function swap(arr, indexA, indexB) { [arr[indexA], arr[indexB]] = [arr[indexB], arr[indexA]] } 为啥用 ES5 的方式来写 function,AirBnb 的 ES6 规范建议不是用 `const` \+ 箭头函数来替代传统的 ES5 `function` 声明式吗? 子曰: * **编程规范是人定的,而你是有选择的**。 * **软件开发不是遵循教条,代码世界本没有标准答案**。 我用传统 ES5 `function` 是因为: 我想*利用它的变量提升实现函数主逻辑前置*,进而从上到下,层层逻辑递进。再一次出现这两个次:*逻辑简洁*、*好维护*。 ## 总结 ## * 你问:有没有高水平的代码来让面试官眼前一亮? * 我答:只有*好读又简洁,稳定易维护*的代码,没有高水平的代码一说。 * 你问:说好的代码品味呢? * 我答:都藏在每一个细节的处理上:) ## 地址 ## 原文地址:[https://www.rayjune.me/2018/03/13/see-code-taste-from-shuffle/][https_www.rayjune.me_2018_03_13_see-code-taste-from-shuffle] 作者:RayJune https://github.com/rayjune 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 [https_www.rayjune.me_2018_03_13_see-code-taste-from-shuffle]: https://www.rayjune.me/2018/03/13/see-code-taste-from-shuffle/
相关 JS面试题 > JS初级开始 > 1.基本数据类型有几种?(高频) String,Boolean,Number,Null,undefiend,Symbol(es6) Symbol: 左手的ㄟ右手/ 2022年09月10日 08:18/ 0 赞/ 156 阅读
相关 js面试题 一、作用域 1、写出console.log结果(作用域) (function(){ var a = b = 2; })() con ╰半橙微兮°/ 2022年05月29日 11:48/ 0 赞/ 176 阅读
相关 js(面试题) shuffle:顾名思义,将数组随机排序,常在开发中用作实现随机功能。 我们来看看一个 shuffle 可以体现出什么代码品味。 错误举例 function 小灰灰/ 2022年05月29日 02:38/ 0 赞/ 164 阅读
相关 js面试题 > 1.JavaScript中如何检测一个变量是一个String类型?请写出函数实现 方法①: function isString(obj){ 深藏阁楼爱情的钟/ 2022年04月02日 04:42/ 0 赞/ 184 阅读
相关 js 面试题 javascript的数据类型 原始类型:null,undefined,number(数字类型),string(字符串类型),boolean(布尔值类型),symbol(e 我会带着你远行/ 2022年03月18日 11:58/ 0 赞/ 214 阅读
相关 JS面试题 1.什么是JavaScript? JavaScript是一种客户端脚本语言,可以插入到HTML页面中,并且是目前较热门的Web开发语言。同时,JavaScript是基于对象 Dear 丶/ 2022年03月08日 10:22/ 0 赞/ 202 阅读
相关 js面试题 JavaScript 的组成 JavaScript 由以下三部分组成: ECMAScript(核心):JavaScript 语言基础 DOM(文档对象模型) 客官°小女子只卖身不卖艺/ 2022年02月22日 19:00/ 0 赞/ 363 阅读
相关 js 面试题 闭包: ![复制代码][copycode.gif] function fun(n,o) { console.log(o) retur 浅浅的花香味﹌/ 2022年02月19日 01:53/ 0 赞/ 202 阅读
相关 js 面试题 1:toString function A() { this.name = "a"; this.toString = 一时失言乱红尘/ 2021年09月20日 13:26/ 0 赞/ 304 阅读
还没有评论,来说两句吧...