【CSDN學院出品】 你不可不知的JS面試題(分期更新……)
1、JS中有哪些內建型別?
7種。分別是boolean
、number
、string
、object
、undefined
、null
、symbol
。
2、NaN是獨立的一種型別嗎?
不是。NaN是number
型別。
3、如何判斷是哪個型別?
Object.prototype.toString.call()
,返回為[object Type]
。
現在我們來驗證一下。
Object.prototype.toString.call(NaN);
// "[object Number]"
Object.prototype.toString.call('1');
// "[object String]"
Object.prototype.toString.call([1,2]);
// "[object Array]"
為什麼使用Object.prototype.toString.call()
,而不用typeof
。是因為它有一點具有侷限性。比如當我們判斷陣列型別時,列印出的是object
,而不是我們想要的Array
。
typeof [1,2];
// "object"
typeof new Number(1);
// "object"
好,既然Object.prototype.toString.call()
這麼好用,我們不如封裝一個方法。
function getType(v) {
return Object.prototype.toString.call(v).match(/\[object (.+?)\]/)[1].toLowerCase();
}
getType(1);
// "number"
4、內建型別之間如何進行型別轉換?
首先,我們先看幾個例子。
第一個例子:
const a = 1;
const b = '1';
if(a==b){
console.log('true') //true
}
第二個例子:
const x = 1+'1';
console.log(x); // 11
const y = 1*'1';
console.log(y); // 1
第三個例子:
const array = [];
if (array) {
console.log('true'); // 返回true
} else {
console.log('false');
}
第四個例子:
if([] == false) {
console.log('true'); //返回true
} else {
console.log('false');
}
如果你還不是不相信第四個例子的操作,那麼我們實際操作一下。果不其然,還是返回true
。
我們先不著急,想它為什麼會返回true
。我們需要知道這兩點。
四則運算轉化:
1. 當遇到和字串做 “加法” 時,會先將其轉化為字串,然後再進行字串相加。
2. 當遇到“減法”、“乘法”、“除法”時,則會將其轉化為數字,然後再進行運算。
對比轉化(==):
- 布林值、字串轉化為數字 ;
- 物件轉化為字串(絕大多數);
- null、undefined、symbol、NaN;
我們先看下對比轉化中的第三點。
null == undefined
,但是不等於其他。
symbol
不等於其他。
NaN
不等於其他,關鍵是和自己都不相等。
好了,轉為正題。第四個例子為什麼會返回ture
。因為[]
先轉化為字串(對比轉化中說過)。使用toString()
方法轉化,也就是''
,然後''
轉化為數字0
,最後false
轉化為0
。0
與0
當然相等。
說了這麼多,我們仔細來講講物件的資料型別轉換。
物件的資料型別轉換
- valueOf
- toString
- Symbol.toPrimitive
我們先來個例子:
let obj = {
valueOf(){
return 1
},
toString(){
return '字元'
}
};
console.log(obj+1);
你是不是會覺得會是[object Object]1
。告訴你,不是哦!而是2
。因為valueOf
、toString
是物件內建的方法。這裡我們只是自定義了一下。我們先來證明一下是不是真的是內建的方法。
valueOf
方法是轉換原始值,也就是自身。toString
方法是轉換為字元。
對了,為什麼是2
呢?這就是物件的資料轉換的靈活性,它會根據自身環境的適應性。轉換自身,這裡我們使用obj+1
,會優先使用數字相加。那麼我們換成alert(obj)
let obj = {
valueOf(){
return 1
},
toString(){
return '字元'
}
};
alert(obj);
這裡則會列印出字元
。因為alert
方法會優先使用字元型別。
最後,我們來講下最後的一個屬性Symbol.toPrimitive
。
let obj = {
valueOf(){
return 1
},
toString(){
return '字元'
},
[Symbol.toPrimitive](){
return 10
}
}
console.log(obj+1) // 11
alert(obj); //10
不論是相加操作,還是alert
彈出。都是執行Symbol.toPrimitive
。因為它的權重最高。
5、this是什麼?
this
指代表當前環境的上下文。
6、如何判斷this的指向
- 預設情況(誰的方法就指向誰)
- 顯示繫結
- 箭頭函式
嚴格模式
第一種情況(誰的方法就指向誰)
1、
var a = 2;
var obj = {
a:1,
getVal(){
console.log(this.a);
}
}
obj.getVal(); //1
2、
class A {
a(){
console.log(this);
}
};
const f = new A();
f.a(); // A {}
3、
function fun() {
console.log(this)
};
fun(); //window,這裡相當於window.fun()。
第二種情況(顯示繫結)
call
、apply
、bind
方法都能顯示改變this
的指向。
var value = 3;
var obj = {
value: 1
}
function get() {
console.log(this.value);
}
get(); // 3
get.call(obj); // 1
get.apply(obj); // 1
get.bind(obj)(); // 1
第三種情況(箭頭函式)
箭頭函式的this
與function
中的this
指向不同,它指向其外部的上下文。
var value = 3;
var obj = {
value: 1,
get: ()=> {
console.log(this.value);
}
}
obj.get(); // 3
第四種情況 (嚴格模式 )
嚴格模式下,方法直接被呼叫的時候,方法內部的this
不會指向window
。
'use strict'
function fun() {
console.log(this)
}
fun(); //undefined
7、什麼是prototype?
prototype
就是原型物件,它是函式所獨有的,它包含了一個函式(類)所有的例項共享的屬性和方法。
function A() {};
A.prototype.get=()=>{
console.log('我是get方法');
}
var a1 = new A();
a1.get(); // 我是get方法
var a2= new A();
a2.get(); // 我是get方法
a1
和a2
都是A
的例項,所以他們都有A
的原型物件上的get
方法屬性。
8、將方法設定在prototype上和設定在建構函式的this上有什麼區別?
function A() {};
A.prototype.get = () => {
console.log('我是A');
}
function B() {
this.get = () => {
console.log('我是B');
}
};
-
繫結在
prototype
上的方法只會在記憶體中儲存一份,每個例項都會根據原型鏈找到建構函式上的這個方法,然後呼叫。 -
繫結在建構函式
this
上的方法會在每次例項化的時候都在記憶體中建立一次,也是new
幾次,就會建立幾次。
9、什麼是__proto__?
_proto_
是瀏覽器內部的屬性,並非js
標準屬性。(一般我們不會直接操作它)- 每個物件都有
_proto_
,且指向建構函式的prototype
。(非常重要,但是null
和undefined
沒有_proto_
)
第二點注意,下面兩個例子都返回true
。
function F() {};
const f = new F();
f.__proto__ === F.prototype?console.log('true'):console.log('false'); //true
const n = new Number(1);
n.__proto__ === Number.prototype?console.log('true'):console.log('false'); // true
10、物件的原型鏈組成?
原型鏈:
function A() {};
const a = new A();
a.__proto__===A.prototype?console.log('true'):console.log('false');//true
console.log(A.prototype); // {constructor:f}
A.prototype.get=()=>{
console.log('這是get')
}
console.log(A.prototype); // {get:f,constructor:f} //列印出為一個物件
// 以下兩行程式碼為舉例
const obj = new Object({get:()=>{},constructor:()=>{}})
console.log(obj);
A.prototype.__proto__===Object.prototype?console.log('true'):console.log('false');//true
11、建構函式的原型鏈?
眾所周知,建構函式也是物件。我們知道建立建構函式有兩種方法。
1、
function A() {};
console.log(A); //ƒ A() {}
2、
const B = new Function();
console.log(B); //ƒ anonymous() {}
所以說,我們看下A.__proto===Function.prototype
是否成立。
function A() {};
A.__proto__===Function.prototype?console.log('true'):console.log('false');//true
同理,建構函式的原型鏈:
驗證一下,
Function.prototype.__proto__===Object.prototype?console.log('true'):console.log('false');//true
那麼,我們又有另一個疑問?Function.__proto__
指向誰呢?
Function.__proto__===Function.prototype?console.log('true'):console.log('false');//true
Function.prototype
比較特殊,它是瀏覽器自身建立出來的內建物件。同樣,Object.prototype
也是瀏覽器引擎建立出來的內建物件,它們都指向null
。
12、prototype上的constructor是什麼?
每一個函式的原型物件上的constructor
都指向函式本身,目前它並沒有什麼作用,或許可以當作instanceof
來使用(當然constructor
的指向也是可以被改變的,不過真的沒啥用)
function A() {};
A.prototype.constructor===A?console.log('true'):console.log('false');//true
function A() {};
const a = new A();
console.log(a instanceof A) // true
13、call、apply、bind的作用是什麼?
它們都是為了改變方法內部this
的指向。
14、call、apply怎麼區別?
call
和apply
第一個引數均為this
的指向。call
的其餘引數就是一個普通的引數列表。apply
除了第一個引數外,只接受一個陣列型別的引數。
call
的用法:
const obj = {name:'maomin'};
function get(age,sex) {
console.log(`
我的名字:${this.name}
我的年齡:${age}
我的性別:${sex}
`)
}
get.call(obj,18,'男');
//我的名字:maomin
//我的年齡:18
//我的性別:男
apply
的用法:
const obj = {name:'maomin'};
function get(age,sex) {
console.log(`
我的名字:${this.name}
我的年齡:${age}
我的性別:${sex}
`)
}
get.apply(obj,[18,'男']);
//我的名字:maomin
//我的年齡:18
//我的性別:男
15、bind與call和apply的不同?
- 第一個引數為
this
的指向,其餘引數是一個普通的引數列表。(這一點跟call
很像) - 返回的是一個函式,需要再呼叫一下。 (
bind
可以實現柯里化)
1、
function get(x,y,z) {
console.log(x,y,z)
}
console.log(get.bind(null,'紅','黃','藍'))
// ƒ (x,y,z) {
// console.log(x,y,z)
// }
get.bind(null,'紅','黃','藍')(); // 紅 黃 藍
2、
function get(x,y,z) {
console.log(this.name,x,y,z)
}
get.bind({name:'maomin'},'紅','黃','藍')(); // maomin 紅 黃 藍
柯里化:
function get(x,y,z) {
console.log(this.name,x,y,z)
}
get.bind({name:'maomin'}).bind(null,'紅').bind(null,'黃').bind(null,'藍')(); // maomin 紅 黃 藍
下一期更新 請關注 第二期
相關文章
- JS物件,你不可不知的知識體系JS物件
- 你不可不知的50個數學知識
- 你不知道的面試題(一)附答案面試題
- 【暫定】你不可不知的50個生物學知識
- 不可不知的JSON處理庫(cJSON)JSON
- 你不可不知的 HTML 優化技巧HTML優化
- 你不可不知的HTML優化技巧HTML優化
- 你不可不知的10個Github功能Github
- 【招募完成】《你不可不知的50個倫理學知識》
- Java經典面試題-不古出品Java面試題
- 優思學院|質量工程師不可不知的DPU、PPM、DPMO、DPO、RTY工程師
- CSDN學院APP 升級公告說明APP
- 原型—-《你不知道的js》原型JS
- 你不知道的js坑JS
- Java經典面試題(二)-不古出品Java面試題
- 《你不可不知的50個建築學知識》之哥特式建築
- 讀<<你不可不知的50個物理知識>>
- 你不可不知的9種Lisp語言思想Lisp
- CSDN學院技術交流群招募中
- 你不知道的JS 筆記JS筆記
- 你可能不知道的JSJS
- 型別—-《你不知道的js》型別JS
- iOS 推送全解析,你不可不知的所有 Tips!iOS
- 【取消】《你不可不知的50個量子物理知識》
- 新款iPod系列不可不知的23個問題
- 【編輯手記】我讀《你不可不知的50個建築學知識》
- 關於面試你不知道的幾點面試
- 《你不知道的JS上》筆記JS筆記
- 你不知道的 Node.js UtilNode.js
- 你不知道的JS(上) 【總結】JS
- 你不知道的JS小黃書(中)JS
- 學習筆記:Android這四個你不可不知的知識點,你都瞭解多少?筆記Android
- 你不可不知道的20個優秀PHP框架PHP框架
- 《你不可不知的50個藝術知識》之抽象畫抽象
- 你不可不知的網際網路創業公司生存技巧創業
- 你不知道的 JSON.stringifyJSON
- 你也許不知道的Vuejs - 前言VueJS
- 《你不可不知的人性》劉墉 讀書筆記(六)筆記