前言
大家好,我是林三心,基礎是進階的前提,今天給大家分享一下,我這一年來工作中遇到的50個「基礎知識點」,我這一年來就有記錄知識點的習慣哈哈。滿分的可以找我拿禮品哦!
50個基礎知識點
1、JavaScript有幾種資料型別?
- number:數字型別
- string:字串型別
- boolean:布林值型別
- undefined:未定義型別
- null:空值型別
- object:物件型別
- symbol:symbol型別
- bigint:大數字型別
2、JavaScript最大安全數字與最小安全數字?
console.log(Number.MAX_SAFE_INTEGER)
// 9007199254740991
console.log(Number.MIN_SAFE_INTEGER)
// -9007199254740991
3、深拷貝與淺拷貝的區別?
- 深拷貝層層拷貝,淺拷貝只拷貝第一層,深層只是引用
- 在深拷貝中,新物件中的更改不會影響原始物件,而在淺拷貝中,新物件中的更改,原始物件中也會跟著改。
- 在深拷貝中,原始物件不與新物件共享相同的屬性,而在淺拷貝中,它們具有相同的屬性。
4、閉包是什麼?
閉包是一個能讀取其他函式內部變數的函式
- 優點:使外部能訪問到區域性的東西
缺點:使用不當容易造成記憶體洩漏的問題
例子:function a () { let num = 0 // 這是個閉包 return function () { return ++num } } const b = a() console.log(b()) // 1 console.log(b()) // 2
5、原型鏈是什麼呀?詳細點!
看看我這篇文章:掘金講「原型鏈」,講的最好最通俗易懂的
6、什麼是變數提升?函式提升?
變數提升
console.log(name) // undefined
var name = 'Sunshine_Lin'
if (false) {
var age = 23
}
console.log(age) // undefined 不會報錯
函式提升
console.log(fun) // function fun() {}
function fun() {}
if (false) {
function fun2(){}
}
console.log(fun2) // undefined 不會報錯
函式提升優先順序 > 變數提升優先順序
console.log(fun) // function fun() {}
var fun = 'Sunshie_Lin'
function fun() {}
console.log(fun) // 'Sunshie_Lin'
7、isNaN 與 Number.isNaN的區別?
- isNaN:除了判斷NaN為true,還會把不能轉成數字的判斷為true,例如'xxx'
- Number.isNaN:只有判斷NaN時為true,其餘情況都為false
8、解決遍歷物件時,把原型上的屬性遍歷出來了咋辦?
使用 hasOwnProperty
判斷
function Person(name) {
this.name = name
}
Person.prototype.age = 23
const person = new Person('Sunshine_lin')
for (const key in person) { console.log(key) } // name age
// 使用 hasOwnProperty
for (const key in person) {
person.hasOwnProperty(key) && console.log(key)
} // name
9、valueOf 與 toString
- 1、
valueOf
偏向於運算,toString
偏向於顯示 - 2、物件轉換時,優先呼叫
toString
- 3、強轉字串優先呼叫
toString
,強轉數字優先呼叫valueOf
- 4、正常情況下,優先呼叫
toString
- 5、運算操作符情況下優先呼叫
valueOf
呼叫valueOf
呼叫者 | 返回值 | 返回值型別 |
---|---|---|
Array | 陣列本身 | Array |
Boolean | 布林值 | Boolean |
Date | 毫秒數 | Number |
Function | 函式本身 | Function |
Number | 數字值 | Number |
Object | 物件本身 | Object |
String | 字串 | String |
呼叫toString
呼叫者 | 返回值 | 返回值型別 |
---|---|---|
Array | 陣列轉字串,相當於Array.join() | String |
Boolean | 轉字串'true'、'false' | String |
Date | 字串日期,如'Fri Dec 23 2016 11:24:47 GMT+0800 (中國標準時間)' | String |
Number | 數字字串 | String |
Object | '[object Object]' | String |
String | 字串 | String |
10、JavaScript變數在記憶體中具體儲存形式?
- 基本資料型別:存在
棧記憶體
裡 - 引用資料型別:指標存
棧記憶體
,指向堆記憶體
中一塊地址,內容存在堆記憶體中 - 也有說法說其實JavaScript所有資料都存
堆記憶體
中,我也比較贊同這種說法
11、講一講JavaScript的裝箱和拆箱?
裝箱:把基本資料型別轉化為對應的引用資料型別的操作
看以下程式碼,s1只是一個基本資料型別,他是怎麼能呼叫indexOf
的呢?
const s1 = 'Sunshine_Lin'
const index = s1.indexOf('_')
console.log(index) // 8
原來是JavaScript內部進行了裝箱操作
- 1、建立String型別的一個例項;
- 2、在例項上呼叫指定的方法;
3、銷燬這個例項;
var temp = new String('Sunshine_Lin') const index = temp.indexOf('_') temp = null console.log(index) // 8
拆箱:將引用資料型別轉化為對應的基本資料型別的操作
通過
valueOf
或者toString
方法實現拆箱操作var objNum = new Number(123); var objStr =new String("123"); console.log( typeof objNum ); //object console.log( typeof objStr ); //object console.log( typeof objNum.valueOf() ); //number console.log( typeof objStr.valueOf() ); //string console.log( typeof objNum.toString() ); // string console.log( typeof objStr.toString() ); // string
12、null和undefined的異同點有哪些?
相同點
- 都是空變數
- 都是假值,轉布林值都是false
- null == undefined 為 true
不同點 - typeof判斷null為object,判斷undefined為undefined
- null轉數字為0,undefined轉數字為NaN
- null是一個物件未初始化,undefined是初始化了,但未定義賦值
- null === undefined 為 false
13、如何判斷資料型別?
- typeof xxx:能判斷出number,string,undefined,boolean,object,function(null是object)
- Object.prototype.toString.call(xxx):能判斷出大部分型別
- Array.isArray(xxx):判斷是否為陣列
14、為什麼typeof null 是object?
不同的資料型別在底層都是通過二進位制表示的,二進位制前三位為 000
則會被判斷為 object
型別,而null底層的二進位制全都是0,那前三位肯定也是 000
,所以被判斷為 object
15、== 與 === 的區別?
- ==:在比較過程中會存在隱式轉換
- ===:需要型別相同,值相同,才能為true
16、JavaScript的隱式轉換規則?
- 1、轉成string型別: +(字串連線符)
- 2、轉成number型別:++/--(自增自減運算子) + - * / %(算術運算子) > < >= <= == != === !=== (關係運算子)
- 3、轉成boolean型別:!(邏輯非運算子)
17、雙等號左右兩邊的轉換規則?
- 1、null == undefined 為 true
- 1、如果有一個運算元是布林值,則在比較相等性之前先將其轉換為數值——false轉換為0,而true轉換為1;
- 2、如果一個運算元是字串,另一個運算元是數值,在比較相等性之前先將字串轉換為數值
- 3、如果一個運算元是物件,另一個運算元不是,則呼叫物件的toString()方法,用得到的基本型別值按照前面的規則進行比較
18、undefined >= undefined 為什麼是 false ?
按照隱式轉換規則
,可轉換成 NaN >= NaN
,NaN 不等於 NaN,也不大於,所以是 false
19、null >= null 為什麼是 true?
按照隱式轉換規則
,可轉換成 0 >= 0
,0 等於 0,所以是 true
20、[] == ![] 為什麼是 true ?
按照雙等號左右兩邊的轉換規則
- 1、
!
優先順序高於==
,[]
不是假值,所以先轉換成[] == false
- 2、右邊為布林值,
false
先轉數字0
,所以可轉換為[] == 0
- 3、左邊為物件,
[]
呼叫toString
轉為''
,轉換為'' == 0
- 4、左邊為字串,
''
轉換為0
,最終為0 == 0
21、0.1 + 0.2 === 0.3,對嗎?
不對,JavaScript的計算存在精度丟失問題
console.log(0.1 + 0.2 === 0.3) // false
- 原因:JavaScript中小數是浮點數,需轉二進位制進行運算,有些小數無法用二進位制表示,所以只能取近似值,所以造成誤差
解決方法:
- 先變成整數運算,然後再變回小數
- toFixed() 效能不好,不推薦
22、什麼是匿名函式?
匿名函式:就是沒有函式名的函式,如:
(function(x, y){
alert(x + y);
})(2, 3);
這裡建立了一個匿名函式(在第一個括號內),第二個括號用於呼叫該匿名函式,並傳入引數。
23、繫結點選事件有幾種方式?
三種
xxx.onclick = function (){}
<xxx onclick=""></xxx>
xxx.addEventListence('click', function(){}, false)
24、addEventListence的第三個引數是幹嘛的?
第三個變數傳一個布林值,需不需要阻止冒泡,預設是false,不阻止冒泡
25、函式宣告和函式表示式的區別?
- 函式宣告:享受函式提升
- 函式表示式:歸類於變數宣告,享受變數提升
函式提升優先順序 > 變數提升優先順序
console.log(fun) // fun () {} // 函式表示式 var fun = function(name) {} // 函式宣告 function fun () {} console.log(fun) // fun (name) {}
26、JavaScript的事件流模型有哪些?
- 事件冒泡:由最具體的元素接收,並往上傳播
- 事件捕獲:由最不具體的元素接收,並往下傳播
- DOM事件流:事件捕獲 -> 目標階段 -> 事件冒泡
27、Ajax、Axios、Fetch有啥區別?
- Ajax:是對XMLHttpRequest物件(XHR)的封裝
- Axios:是基於Promise對XHR物件的封裝
- Fetch:是window的一個方法,也是基於Promise,但是與XHR無關,不支援IE
28、load、$(document).ready、DOMContentLoaded的區別?
DOM文件載入的步驟為:
- 1、解析HTML結構。
- 2、載入外部指令碼和樣式表檔案。
- 3、解析並執行指令碼程式碼。
- 4、DOM樹構建完成。//
DOMContentLoaded
觸發、$(document).ready
觸發 - 5、載入圖片等外部檔案。
- 6、頁面載入完畢。//
load
觸發
29、如何阻止事件冒泡?
function stopBubble(e) {
if (e.stopPropagation) {
e.stopPropagation()
} else {
window.event.cancelBubble = true;
}
}
30、如何阻止事件預設行為?
function stopDefault(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
window.event.returnValue = false;
}
}
31、什麼是事件委託?
當所有子元素都需要繫結相同的事件的時候,可以把事件繫結在父元素上,這就是 事件委託
,優點有:
- 繫結在父元素上只需要繫結一次,節省效能
- 子元素不需要每個都去繫結同一事件
- 如果後續又有新的子元素新增,會由於事件委託的原因,自動接收到父元素的事件監聽
32、如何實現陣列去重?
// 使用 Map 去重
function quchong1(arr) {
const newArr = []
arr.reduce((pre, next) => {
if (!pre.get(next)) {
pre.set(next, 1)
newArr.push(next)
}
return pre
}, new Map())
return newArr
}
// 使用 Set 去重
function quchong (arr) {
return [...new Set(arr)]
}
33、Set與Array的區別是什麼?
建議看阮一峰老師的文章:Set 和 Map 資料結構
34、Map與Object的區別是什麼?
建議看阮一峰老師的文章:Set 和 Map 資料結構
35、NaN是什麼?有什麼特點?
- NaN不等於自身,也就是
NaN === NaN
為false
- NaN為假值,轉布林值為
false
- NaN本質是一個number,
typeof NaN === number
36、處理非同步的方法有哪些?
- 回撥函式
- promise
- 事件監聽
- 釋出訂閱
async await
37、JavaScript繼承方式有幾種?
前置工作
// 定義一個動物類 function Animal (name) { // 屬性 this.name = name || 'Animal'; // 例項方法 this.sleep = function(){ console.log(this.name + '正在睡覺!'); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); };
1、原型鏈繼承
核心:將父類的例項作為子類的原型
function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; var cat = new Cat(); console.log(cat.name); // cat cat.eat('fish') // cat正在吃:fish cat.sleep() // cat正在睡覺! console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
優點:
- 1、非常純粹的繼承關係,例項是子類的例項,也是父類的例項
- 2、父類新增原型方法/屬性,子類都能訪問到
- 3、簡單,易於實現
缺點: - 1、要想為子類新增屬性和方法,必須要在
new Animal()
這樣的語句之後執行,不能放構造器中 - 2、來自原型物件的所有屬性被所有例項共享
- 3、建立子例項時,無法向父類建構函式傳參
- 4、不支援多繼承
2、構造繼承
核心:使用父類的構造器來增強子類例項,等於是複製父類的例項屬性給子類(沒用到原型)
function Cat(name) {
Animal.call(this);
this.name = name || 'Tom';
}
var cat = new Cat();
console.log(cat.name); // Tom
cat.sleep() // Tom正在睡覺!
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
優點:
- 1、解決了
原型鏈繼承
中,子類例項共享父類引用屬性的問題 - 2、建立子類例項時,可以向父類傳遞引數
- 3、可以實現多繼承(call多個父類物件)
缺點: - 1、例項並不是父類的例項,知識子類的例項
- 2、是能繼承父類的例項屬性和方法,不能繼承原型屬性/方法
- 3、無法實現函式複用,每個子類都有父類例項函式的副本,影響效能
3、例項繼承
核心:為父類例項新增新特性,作為子類例項返回
function Cat(name){
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
var cat = new Cat();
console.log(cat.name) // Tom
cat.sleep() // Tom正在睡覺!
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
優點:
- 1、不限制呼叫方式,不管是
new 子類()
還是子類()
,返回的物件具有相同效果
缺點: - 1、例項是父類的例項,不是子類的例項
- 2、不支援多繼承
4、拷貝繼承
核心:就一個一個拷貝
function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
this.name = name || 'Tom';
}
var cat = new Cat();
console.log(cat.name); // Tom
cat.sleep() // Tom正在睡覺!
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
優點:
- 1、支援多繼承
缺點: - 1、效率低,記憶體佔用高(因為要拷貝父類的屬性)
- 2、無法獲取父類不可列舉方法(不可列舉方法,不能使用for in訪問到)
5、組合繼承
核心:通過父類構造,繼承父類的屬性並保留傳參的有點,然後通過將父類例項作為子類原型,實現函式複用
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat = new Cat();
console.log(cat.name); // Tom
cat.sleep() // Tom正在睡覺!
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
優點:
- 1、彌補了
構造繼承
的缺陷,可以繼承例項屬性/方法,也可繼承原型屬性/方法 - 2、既是子類的例項,也是父類的例項
- 3、不存在引用屬性共享問題
- 4、可傳參
- 5、函式可複用
缺點: - 1、呼叫了兩次父類建構函式,生成了兩份例項(子類例項將子類原型上的那份遮蔽了)
6、寄生組合繼承
核心:通過寄生方式,砍掉父類的例項屬性,這樣,在呼叫兩次父類的構造時,就不會初始化兩次例項方法/屬性,避免 繼承組合
的缺點
function Cat(name) {
Animal.call(this);
this.name = name || 'Tom';
}
// 建立一個沒有例項方法的類
var Super = function () { };
Super.prototype = Animal.prototype;
//將例項作為子類的原型
Cat.prototype = new Super();
// Test Code
var cat = new Cat();
console.log(cat.name); // Tom
cat.sleep() // Tom正在睡覺!
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
優點:
- 1、堪稱完美
缺點: - 1、實現複雜
38、建立一個物件的方式有哪幾種?
new Object建立
const obj = new Object()
obj.name = 'Sunshine_Lin'
字面量建立
const obj = { name: 'Sunshin_Lin' }
工廠模式建立
function createObj(name) {
const obj = new Object()
obj.name = name
return obj
}
const obj = createObj('Sunshine_Lin')
建構函式建立
function Person(name) {
this.name = name
}
const person = new Person('Sunshine_Lin')
39、this指向的四種情況?
1、new操作符建立例項
function Person(name) { this.name = name console.log(this) } // this指向當前person例項物件 const person = new Person('Sunshine_Lin')
2、指向window
function fn() { console.log(this) } fn() // 瀏覽器window,node裡global
3、物件呼叫方法
const target = { fn: function () { console.log(this) } } target.fn() // target // 這種就是改變了this了 const fn = target.fn fn() // 瀏覽器window,node裡global
4、call、apply、bind改變this
const obj1 = { name: '林三心', sayName: function() { console.log(this.name) } } const obj2 = { name: 'Sunshin_Lin' } // 改變sayName的this指向obj2 obj1.sayName.call(obj2) // Sunshin_Lin // 改變sayName的this指向obj2 obj1.sayName.apply(obj2) // Sunshin_Lin // 改變sayName的this指向obj2 const fn = obj1.sayName.bind(obj2) fn() // Sunshin_Lin
40、陣列的常用方法有哪些?
方法 | 作用 | 是否影響原陣列 |
---|---|---|
push | 在陣列後新增元素,返回陣列長度 | ✅ |
pop | 刪除陣列最後一項,返回被刪除項 | ✅ |
shift | 刪除陣列第一項,並返回陣列 | ✅ |
unshift | 陣列開頭新增元素,返回新增的元素 | ✅ |
reserve | 反轉一個陣列,返回修改後的陣列 | ✅ |
sort | 排序一個陣列,返回修改後的陣列 | ✅ |
splice | 擷取陣列,返回被擷取的區間 | ✅ |
join | 將一個陣列所有元素連線成字串並返回這個字串 | ❌ |
concat | arr1.concat(arr2, arr3) 連線陣列 | ❌ |
join | arr.join(x)將arr陣列元素連線成字串並返回這個字串 | ❌ |
map | 運算元組每一項並返回一個新陣列 | ❌ |
forEach | 遍歷陣列,沒有返回值 | ❌ |
filter | 對陣列所有項進行判斷,返回符合規則的新陣列 | ❌ |
every | 陣列每一項都符合規則才返回true | ❌ |
some | 陣列有符合規則的一項就返回true | ❌ |
reduce | 接收上一個return和陣列的下一項 | ❌ |
flat | 陣列扁平化 | ❌ |
slice | 擷取陣列,返回被擷取的區間 | ❌ |
41、Math的常用方法有哪些?
方法 | 作用 |
---|---|
Math.max(arr) | 取arr中的最大值 |
Math.min(arr) | 取arr中的最小值 |
Math.ceil(小數) | 小數向上取整 |
Math.floor(小數) | 小數向下取整 |
Math.round(小數) | 小數四捨五入 |
Math.sqrt(num) | 對num進行開方 |
Math.pow(num, m) | 對num取m次冪 |
Math.random() * num | 取0-num的隨機數 |
42、哪些因素導致記憶體洩漏?如何解決?
請看我這篇文章哪是大神?只是用他人七夕約會時間,整理「JS避免記憶體洩漏」罷了
43、講講JavaScript的垃圾回收機制
看我這篇文章:贈你13張圖,助你20分鐘打敗了「V8垃圾回收機制」
44、JS中有哪些不同型別的彈出框?
在JS中有三種型別的彈出框可用,分別是:
- Alert
- Confirm
Prompt
45. 如何將 JS 日期轉換為ISO標準
toISOString() 方法用於將js日期轉換為ISO標準。 它使用ISO標準將js Date物件轉換為字串。如:
var date = new Date();
var n = date.toISOString();
console.log(n);
// YYYY-MM-DDTHH:mm:ss.sssZ
46、如何在JS中編碼和解碼 URL
encodeURI() 函式用於在JS中對URL進行編碼。它將url字串作為引數並返回編碼的字串。
注意: encodeURI()不會編碼類似這樣字元: / ? : @ & = + $ #,如果需要編碼這些字元,請使用encodeURIComponent()。 用法:
var uri = "my profile.php?name=sammer&occupation=pāntiNG";
var encoded_uri = encodeURI(uri);
decodeURI() 函式用於解碼js中的URL。它將編碼的url字串作為引數並返回已解碼的字串,用法:
var uri = "my profile.php?name=sammer&occupation=pāntiNG";
var encoded_uri = encodeURI(uri);
decodeURI(encoded_uri);
47、什麼是BOM?有哪些api?
BOM就是 browser object model
, 瀏覽器物件模型
api | 作用 | 代表方法或屬性 |
---|---|---|
window.history | 操縱瀏覽器的記錄 | history.back() history.go(-1) |
window.innerHeight | 獲取瀏覽器視窗的高度 | |
window.innerWidth | 獲取瀏覽器視窗的寬度 | |
window.location | 操作重新整理按鈕和位址列 | location.host:獲取域名和埠 location.hostname:獲取主機名 location.port:獲取埠號 location.pathname:獲取url的路徑 location.search:獲取?開始的部分 location.href:獲取整個url location.hash:獲取#開始的部分 location.origin:獲取當前域名 location.navigator:獲取當前瀏覽器資訊 |
48、BOM 和 DOM 的關係
BOM全稱Browser Object Model,即瀏覽器物件模型,主要處理瀏覽器視窗和框架。
DOM全稱Document Object Model,即文件物件模型,是 HTML 和XML 的應用程式介面(API),遵循W3C 的標準,所有瀏覽器公共遵守的標準。
JS是通過訪問BOM(Browser Object Model)物件來訪問、控制、修改客戶端(瀏覽器),由於BOM的window包含了document,window物件的屬性和方法是直接可以使用而且被感知的,因此可以直接使用window物件的document屬性,通過document屬性就可以訪問、檢索、修改XHTML文件內容與結構。因為document物件又是DOM的根節點。
可以說,BOM包含了DOM(物件),瀏覽器提供出來給予訪問的是BOM物件,從BOM物件再訪問到DOM物件,從而js可以操作瀏覽器以及瀏覽器讀取到的文件。
49、JS中的substr()和substring()函式有什麼區別
substr() 函式的形式為substr(startIndex,length)。 它從startIndex返回子字串並返回'length'個字元數。
var s = "hello";
( s.substr(1,4) == "ello" ) // true
substring() 函式的形式為substring(startIndex,endIndex)。 它返回從startIndex到endIndex - 1的子字串。
var s = "hello";
( s.substring(1,4) == "ell" ) // true
50、解釋一下 "use strict" ?
“use strict”是Es5中引入的js指令。 使用“use strict”指令的目的是強制執行嚴格模式下的程式碼。 在嚴格模式下,我們們不能在不宣告變數的情況下使用變數。 早期版本的js忽略了“use strict”。
結語
如果你覺得此文對你有一丁點幫助,點個贊,鼓勵一下林三心哈哈。或者可以加入我的摸魚群
想進學習群,摸魚群,請檢視我首頁加我,並備註:思否,我會定時直播模擬面試,答疑解惑
滿分的趕緊找我!!!或者評論區告訴我哦~~~