座標杭州,18年畢業,算上實習一年半開發經驗。是外派的面試,後面兩面都是阿里的面試官。css
原本是給我發的在線測評,可是那邊服務器出現問題,我一直打不開網頁,最後只好以電話問答的形式。下面我寫的大部分都是測評裏的題目,部分是電話裏新增的題目。。。html
<div class="father">
<div class="child">
</div>
</div>
<style> .father { width: 300px; height: 300px; } .child { } </style>
複製代碼
child分不少種狀況,大體說一下react
.father{
text-align: center;
line-height: 300px;
}
複製代碼
.father{
position: relative;
}
.child{
position: absolute;
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
}
/* 或者 */
.child{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
複製代碼
.father{
position: relative;
}
.child{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
複製代碼
.father{
display: flex;
}
.child{
margin:auto;
}
/* 或者 */
.child{
justify-content: center;
align-items: center;
}
複製代碼
.father{
display: table;
}
.child{
display: table-cell;
text-align: center;
vertical-align: middle;
}
複製代碼
<div class="container">
<div class="main"></div>
<div class="sub"></div>
<div class="extra"></div>
</div>
複製代碼
console.log(+false) // 0, 這裏是一元運算符進行的弱類型轉換,相對應的 +true 則返回 1
console.log('1' + 2 + '3' + 4) // '1234' 遇到字符串就會拼接
console.log(4 + 3 + 2 + '1') // '91' 先加在一塊兒再拼接
複製代碼
var x = 3;
var foo = {
x: 2,
baz: {
x: 1,
bar: function() {
return this.x;
}
}
}
var go = foo.baz.bar;
console.log(go()); // 3
console.log(foo.baz.bar()); // 1
複製代碼
這題考的是this的指向:面試
this由調用者提供,由調用函數的方式來決定。若是是一個對象調用的函數,則this指向該對象,好比
foo.baz.bar()
。若是函數獨立調用好比go()
,那麼該函數內部的this,則指向undefined。可是在非嚴格模式中,它會被自動指向全局對象window。算法
function reverse(str) {
let res = str.split('');
return res.reverse().join('');
}
reverse('hello world!'); // output: '!dlrow olleh'
複製代碼
進階問題編程
'hello world!'.reverse(); // output: '!dlrow olleh'
複製代碼
String.prototype.reverse = function reverse() {
let res = this.split('');
return res.reverse().join('');
}
複製代碼
要求用法:redux
/** - 使當前運行的異步操做(promise 或者 async)中止等待若干秒 - - @param ms */
(async () => {
console.log('hello')
await sleep(2000) // 等待兩秒
console.log('world')
})()
複製代碼
const sleep = (ms) => {
new Promise(resolve, reject) {
setTimeOut(() => {
resolve(); // 大體這樣?
}, ms)
}
}
複製代碼
用法:api
const throFun = () => console.log('hello');
const thro = throttle(throFun, 300);
document.body.onscroll = () => {
thro(); // 調用至少間隔 300 毫秒纔會觸發一次
}
複製代碼
/** - 頻率控制,返回函數連續調用時,action 執行頻率限定爲 1次 / delay - @param delay {number} 延遲時間,單位毫秒 - @param action {function} 請求關聯函數,實際應用須要調用的函數 - @return {function} 返回客戶調用函數 */
function throttle(action, delay) {
var previous = 0;
// 使用閉包返回一個函數而且用到閉包函數外面的變量previous
return function() {
var _this = this;
var args = arguments;
var now = new Date();
if(now - previous > delay) {
action.apply(_this, args);
previous = now;
}
}
}
複製代碼
用法:數組
const throFun = () => console.log('hello');
const thro = debounce(throFun, 300);
document.body.onscroll = () => {
thro(); // 若一直調用則不會執行,空閒時間大於 300 毫秒纔會執行
}
複製代碼
/** - 空閒控制 返回函數連續調用時,空閒時間必須大於或等於 delay,action 纔會執行 - @param delay {number} 空閒時間,單位毫秒 - @param action {function} 請求關聯函數,實際應用須要調用的函數 - @return {function} 返回客戶調用函數 */
function debounce(action, delay) {
var timer; // 維護一個 timer
return function () {
var _this = this; // 取debounce執行做用域的this
var args = arguments;
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
action.apply(_this, args); // 用apply指向調用debounce的對象,至關於_this.action(args);
}, delay);
};
}
複製代碼
const arr = [1,2,3,4,4,3,2,1];
// 方法一:new Set ES6
return [...new Set(arr)]; // 這裏又問到我...的用法
// 方法二:雙層for循環 (而後說這樣性能很差,讓我只用一層for循環的方法)
function unique(arr){
var res=[];
for (var i = 0; i < arr.length; i++) {
for (var j = i+1; j < arr.length; j++) {
if (arr[i] === arr[j]) {
++ i;
j = i;
}
}
res.push(arr[i]);
}
return res;
}
// 方法三:單層for循環 + indexOf
function unique(array){
var res = [];
for(var i = 0; i < array.length; i++) {
//若是當前數組的第i項在當前數組中第一次出現的位置是i,才存入數組;不然表明是重複的
if (array.indexOf(array[i]) === i) {
res.push(array[i])
}
}
return res;
}
// 方法三點三:或者這樣
function unique(array){
let res = [];
for(var i = 0; i < array.length; i++) {
if (res.indexOf(array[i]) === -1) {
res.push(array[i]);
}
}
return res;
}
// 方法四:面試官說若是能夠容忍改變原有數組的狀況下,怎麼改進性能更好
function unique(array){
// 注意這裏必定要倒敘for循環,不然會出現問題
for(var i = array.length - 1; i > 0; i--) {
if (array.indexOf(array[i]) !== i) {
array.splice(i, 1);
}
}
// 由於少聲明一個變量,節省了內存空間(雖然能夠忽略不計,可是面試嘛~)
return array;
}
複製代碼
題目描述:promise
實現思路:
面試事後整理的代碼:
window.addEventListener('click', (e) => {
let targetNode = e.target
while (targetNode !== document) { // 只要當前節點不是最外層document
console.log(targetNode)
if (targetNode.getAttribute('data-href')) { // 其實用hasAttribute更合適
window.open(targetNode.dataset.href)
break
} else { // 沒找到就繼續往上找
targetNode = targetNode.parentNode
}
}
})
複製代碼
總結:
contains()
方法,而後面試官考慮性能,最好用原生api。而後我就說用parentNode。後來我查了一下MDN,發現contains
這個方法就是原生的api,IE5以上就支持了:
可是這也不是重點,重點是用contains這個方法不能實現這個場景,由於你須要父節點(上層節點)是已知的。但這個場景是經過已知子節點(點擊事件返回的target)來向上尋找節點。getAttribute()
。1.Redux 鼓勵一個應用只用一個 Store,Mobx 鼓勵使用多個 Store; 2.Redux 是函數式編程,而Mobx的模式是面向對象的; 3.Redux 使用「拉」的方式使用數據,這一點和 React是一致的,但 Mobx 使用「推」的方式使用數據; 4.Redux 鼓勵數據範式化,減小冗餘,Mobx 允許數據冗餘,但一樣能保持數據一致。 5.Redux更嚴格,必須調用reducer觸發action來改變state, Mobx 最初的一個賣點就是直接修改數據,可是實踐中你們仍是發現這樣無組織無紀律很差,因此後來 Mobx 仍是提供了 action 的概念。和 Redux 的 action 有點不一樣,Mobx 中的 action 其實就是一個函數,不須要作 dispatch。若是想強制要求使用 action,禁止直接修改 observable 數據,使用 Mobx 的 configure,以下:
import {configure} from 'mobx'; configure({enforceActions: true}); 複製代碼