# 阿里前端算法題 ``` /** * 编码题一:判断括号匹配 * 说明:给定一个只包含 '() {} []' 6种字符的字符串, * 实现一个方法来检测该字符串是否合法,其规则为'()'、'{}'、'[]'必须互相匹配,可嵌套。 * 示例: * isValid('('); // false * isValid('()'); // true * isValid('()[]{}'); // true * isValid('{()[]}'); // true * isValid('(]'); // false * isValid('([)]'); // false * isValid('({}[]([]))'); // true */ //我的答案: // 1.用stack特性 function isValid(input){ var stack = {}; var size = 0; var left = ['(', '[', '{']; var right = [')', ']', '}']; for(var i = 0; i < input.length; i++){ if( left.indexOf(input[i]) !== -1 ){ stack[size] = input[i]; size++; } else if( right.indexOf(input[i]) !== -1 ){ if(size === 0) { return false; } var index = right.indexOf(input[i]); if(stack[size-1] === left[index] ){ size = size-1; } else { return false; } } } return size === 0; } /** * 编码题二:数组按嵌套层次输出 * 说明:给定一个嵌套数组,输出每层的内容 * 示例: * parseArrayLevels([1, [3, ['x', 'y'], 2], [[5], 'a']]); * 输出:[[1], [3, 2, 'a'], ['x', 'y', 5]] */ //我的答案: // 使用split() 方法 // (recursion 的solution寫不出來) function parseArrayLevels(arr) { /** 代码实现 */ // 方法1. let stringList = arr.toString().split("'").filter(ele=>{ return ele }) return stringList }; /** * 编码题三:字符串压缩 * 说明:将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串。 * 压缩规则: * 1、仅压缩连续重复出现的字符。比如字符串“abcbc”由于无连续重复字符,压缩后的字符串还是”abcbc” * 2、压缩字段的格式为”字符重复的次数+字符” * 示例: * stringZip('cccddecc'); // '3c2de2c' * stringZip('adef'); // 'adef' * stringZip('aaaaa'); // '5a' */ //我的答案: 用object['a'] 鍵值 這種方法 來記數 (答案有錯) function stringZip(str) { /** 代码实现 */ let obj = {} for(let i=0;i<str.length;i++){ //如果還沒碰過 初始設1 obj[str[i]] = obj[str[i]] +1 || 1 } let result = '' for (const [key, value] of Object.entries(obj)) { //拼接字符串 if(parseInt(value)===1){ result += (key) }else{ result += (key) + (value) } } return result }; /** * 编码题四:实现一个检验对象是否循环指向的方法 * 说明:当一个对象存在对自身引用时,称之为循环指向 * 如`var o = { a: {} }; o.a = o;` * o -> a -> o,就形成循环指向 * 示例: * isCyclic(window); // true * isCyclic({}); // false * var o = {}; o.o = o; * isCyclic(o); // true * * var obj = { foo: { bar: { baz: { qux: {} } } } }; * obj.foo.bar.baz.qux = obj.foo; * isCyclic(obj); // true */ //我的答案: // 使用JSON.stringify 的特性 , JSON.stringify 會拋異常 如果有 循环指向 // (recursion 的solution寫不出來) function isCyclic (obj) { /* 代码实现 */ try { JSON.stringify(obj); return false; } catch (e) { return true; } } /** * 编码题五:实现一个评星方法 * 说明: * 1. 可根据传入的评分和总数,返回评星结果(用 ★ 和 ☆ 描述) * 2. 评分必选项,四舍五入,总数可选,大于0的整数,默认为5 * 3. 对于评分为空或小于0、评分大于总数、总数小于0或总数非整数的情况,返回'errror' * * 示例: * getRate(4); // ★★★★☆ * getRate(4, 8); // ★★★★☆☆☆☆ * getRate(3.4); // ★★★☆☆ * getRate(5, 2); // 'error' * getRate(-2); // 'error' * getRate(3, 5.5); // 'error' */ //我的答案: //用Math.round()四捨五入 並用數組創建result function getRate(stars,max=5) { /* 代码实现 */ stars = parseInt(stars) stars = Math.round(stars) max = parseInt(max) if(!stars || stars<0 || stars>max){ return 'error' } let result =[] for(let i=0;i<max;i++){ result.push("☆") } for(let i=0;i<stars;i++){ result[i] = '★' } return result.join("") } ``` # 阿里前端題 # thread vs process ### 我的回答: threads run in a shared memory space, and processes run in separate memory spaces. linux 下 命令有 ps ,top , # 講講項目經驗碰到的難點 ### 我的回答: 在之前的項目裡 數據加密沒有做過 文件上傳也沒有做過..... # javascript代码执行的时候会将不同的变量存于内存中的不同位置:堆(heap)和栈(stack) 你來講講 ### 我的回答: 我猜 heap 是 new 出來的dynamic allowcate space 跟c++ 一樣 從動態的 stack 存些 interger 跟string # 项目中如何处理安全问题 後端的話 加密算法 有 Encryption 跟 Hashing, 密碼用 Hashing 因為難破解 然後前端多對數據檢查 不要相信user input # 前端性能提升大致分几类 1. 代碼判斷 少發請求 能合併就合併 2. 少render 避免dom re-render 3. 少用event listener 用了要刪 # 拼室友前端考題 1. 什么是深拷贝,和浅拷贝有什么区别,动手实现一个深拷贝 ### 我的回答: 像c++中的 copy contrucotor 每個 兒子孫子都copy到 ``` function cloneDeep(obj) { if(obj === null) return null; if (typeof obj !== 'object') return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); // 获取obj的构造函数并实例化一个新的 const cloneObj = new obj.constructor(); Object.keys(obj).forEach(key => { // 递归拷贝属性 cloneObj[key] = cloneDeep(obj[key]); }); return cloneObj; } ``` 2. setTimeout 与 setInterval 区别 ### 我的回答: setTimeout 只跑一次 setInterval 能一直跑 然後都是異步任務 3. 说一下 base64 的编码方式 ### 我的回答: 用在傳輸 不是加密 原理不知道 unix 下 可以直接這樣轉換 ``` echo '我將被轉' | base64 ``` ### javascript 的 Promise.then 是什麼 ### 我的回答: 異步編程的方法 解決call back hill ,代碼變得的好讀 ``` var databaseQuery = new Promise((resolve, reject) => { resolve('Success!'); }); databaseQuery.then(value => { console.log("查找成功"); }.err (msg => { console.log("查找失敗"); }) ``` ### 介绍下 javascript 的this ### 我的回答: this 指向當前scope 的對象 全局就指向 window 一般都由內而外 ### Linux 754 是什麼 有個command 叫chmod 管 read,write permission的 777 是大家都能看 , 754 好像是 group 的不能看 ### 講一下JavaScript中的Event Loop 因為javascript是 single thread 所以 要靠 Event Loop 來處理異步任務 但細節我沒有搞懂 ### http 100 是什麼 不知道 但肯定不常用 一般都是200 是好的 300 redirect , 400 canot find , 500 internal error # 騰訊 ``` // - 3. 用JS写一个函数,进行字符串大数相加,输入'56789'+'56789',输出'113578' function add (a, b) { let max = a.length > b.length ? a.length :b.length ; a = a.padStart(max, '0'); b = b.padStart(max, '0'); let result = []; for (let i = max - 1; i >= 0; i--) { let sum = Number(a[i]) + Number(b[i]) + (result[0] ? result[0] : 0); let digit = sum % 10; let carry = Math.floor(sum / 10); result[0] = digit; result.unshift(carry); } return result.toString(); } ``` # 騰訊 ``` function add(a ,b){ //取两个数字的最大长度 let maxLength = Math.max(a.length, b.length); //用0去补齐长度 a = a.padStart(maxLength , 0);//"0009007199254740991" b = b.padStart(maxLength , 0);//"1234567899999999999" //定义加法过程中需要用到的变量 let t = 0; let f = 0; //"进位" let sum = ""; for(let i=maxLength-1 ; i>=0 ; i--){ t = parseInt(a[i]) + parseInt(b[i]) + f; f = Math.floor(t/10); sum = t%10 + sum; } if(f == 1){ sum = "1" + sum; } return sum; } ```