# 前端工程師 javascript 面試問題紀錄
近期開始面試多家公司,這邊整理出筆試或面試上遇到的問題,希望可以幫助到需要的人還有我自己也能複習。
**[參考網址做額外補充!](https://www.explainthis.io/zh-hant/swe-questions/frontend)**
### 下列有哪些屬性是傳址(call by reference)特性?
> Array、Number、Function、Object、String、Undefined
**ans:**
|| Array、Function、Object ||
說明:
js的資料類型(data type)分為兩大類,一種是原始型別(primitive type)和物件(object)。
- 原始型別有:
- Number
- String
- Null
- BigInt
- Boolean
- **Undefined**
- Symbol
- Object:
- 除了原始型態以外的型態,如 array、function、object、map...
簡單說明結論,object型態的類型基本上就是傳址的特性,在呼叫使用時,會是使用到該物件上的地址,如果在物件屬性中重新賦值的話會有參考改變的特性,需要注意。
---
### 下列輸出結果為?
1. console.log(undefined === undefined);
2. console.log(NaN == NaN);
3. console.log(isNaN('NIHOW'));
4. console.log({} === '[object Object]');
5. console.log(0.1+0.2 == 0.3);
6. console.log(typeof[1,2,3]== 'array');
7. console.log(null == undefined);
8. console.log(null === undefined);
**ans:**
|| 1. true
2. false
3. true
4. false
5. false
6. false
7. true
8. false||
---
### 請解釋變數和函式宣告提升(Hoisting)? 下列結果為?
```javascript!
function foo(param) {
console.log(num);
console.log(param);
console.log(arguments[1]);
say();
var num = 1;
function say(){
console.log(2+num);
}
return 33;
}
foo('4','5');
```
**ans:**
1. 變數提升: 當使用`var`宣告時,此變數會被提升到其所在函式或作用域的頂部,表示可以再宣告前就使用該變數,但是他的值會是`undefined`。
2. 函數提升: js中的function也會如此,因此也能在函數宣告之前就調用了。
3. || undefined '4' '5' NaN ||
答案說明:要注意看宣告前後,我在寫題目時寫出的答案是錯的,因為我沒有注意到`say()`函式執行下` var num` 的位置,所以答錯了QQ。
---
### 請問下列 A、B、C、D、E、F 各自打印了幾次?
```javascript!
for(let i = 0; i <= 10; i++) {
console.log('A');
for(let j = 0; j < 10; j++) {
console.log('B');
if(i == 3 && j == 6) {
console.log('C');
}
if(i==j) {
console.log('D');
}
if(i&&j) {
consolog.log('E');
}
}
}
```
**ans:**
||A: 11 次(0~10共11次打印)
B: 110 次(第一層陣列11次 x 第二層陣列10次(<=10) = 110)
C: 1 次
D: 10 次(i跟j為0~9時才會打印,所以是10次)
E: 90 次(這個判斷相等於判斷i跟j是否都不是0也就是說判斷是否存在)||
```javascript!
let j = 0;
while(j <= 100) {
console.log('F')
}
```
**ans:**
|| 無限次 因為沒有設置終止條件,可以在log下面增加 j++; 就不會無限打印了 ||
---
### 1綜合判斷 :
```javascript!
var obj ={};
console.log(delete obj.p);
```
**ans:**
|| true ||
### 2綜合判斷 :
```javascript!
const a = {}
const b = {key: 'b'}
const c = {key: 'c'}
a[b] = 123
a[c] = 456
console.log(a[b])
```
**ans:**
|| 456 ||
### 3綜合判斷 :
```javascript!
let obj = {name:'jimmy', age:18};
let obj1 = obj;
obj.name = 'chimmy'
console.log(obj1)
obj1 = {}
obj.age = 22
console.log(obj1)
```
**ans:**
|| {name: 'chimmy', age: 18}
{}
||
說明:
||注意重新賦值的位置,當obj1重新賦值後他就不再和obj1為相同位"址"了,所以會是空的。||
### 4綜合判斷:
```javascript!
var f = function() {
console.log('1');
}
function f(){
console.log('2');
}
f()
```
**ans:**
|| 1 ||
說明: 因為提升的關係,`var f` 跟 `function f` 都被提升到最頂部,接著執行賦值的 `function() {console.log('1')}`,因為函數聲明(就是"=")會覆蓋函式,所以當在使用`f()`其實就只會觸發到聲明中的log '1'。
### 5綜合判斷:
```javascript!
function Student(name) {
this.name = name;
console.log(this);
}
var result = new Student('jimmy');
```
**ans:**
|| Student {name: 'jimmy'} ||
### 6綜合判斷:
```javascript!
var name = 'jimmy';
var student = {
name: 'chimmy',
doSth: function() {
console.log(this.name)
},
doSth2: function() {
var arrowDoSth = () => {
console.log(this.name);
}
arrowDoSth();
},
doSth3: () => {
console.log(this.name);
}
}
student.doSth()
student.doSth2()
student.doSth3()
```
**ans:**
|| 'chimmy' 'chimmy' 'jimmy'||
說明:
箭頭函式不會創造自己的`this`,所以看到箭頭函式要往上看他繼承的外部函式的this對象,外部函式只到誰,箭頭函式的this就會是誰,所以doSth2中的this其實也指向student本身。
### 1請寫出下列程式碼執行結果:
```javascript!
var name = 'my name is window'
var obj = {
name: 'my name is obj',
fn: function () {
setTimeout( () => {
console.log(this.name)
}, 1000)
}
}
obj.fn()
```
|| my name is obj ||
說明:
因為閉包的特性,函式在使用時會保留上下文所以就算外面有個全域變數,箭頭函式下的this還是會指回原本的obj當中。
### 2請寫出下列程式碼執行結果:
```javascript!
const obj = {a:'one', b:'two', a: 'three'}
console.log(obj)
```
||SybtaxError 重複屬性名||
### 請倒敘印出Array中的內容,並且使用Array.prototype中的reduce完成
```javascript!
const numbers = [0,1,2,3,4,5,6,7]
function revertNumbers(params){
const ans = []
params.reduce(function(total, el) {
ans.unshift(el)
return total // 返回已累積的陣列
},[])// 空陣列是提供reduce方法做初始的累積紀錄
// 如果要回傳字串就用ans.join('')
return ans
}
revertNumbers(numbers)
```