30+ 個(gè)工作中常用到的前端小知識(干貨)
1. JS為什么單線程
一個(gè)簡單的原因就是,js在設(shè)計(jì)之初只是進(jìn)行一些簡單的表單校驗(yàn),這完全不需要多線程,單線程完全可以勝任這項(xiàng)工作。即便后來前端發(fā)展迅速,承載的能力越來越多,也沒有發(fā)展到非多線程不可的程度。
而且還有一個(gè)主要的原因,設(shè)想一下,如果js是多線程的,在運(yùn)行時(shí)多個(gè)線程同時(shí)對DOM元素進(jìn)行操作,那具體以哪個(gè)線程為主就是個(gè)問題了,線程的調(diào)度問題是一個(gè)比較復(fù)雜的問題。
HTML5新的標(biāo)準(zhǔn)中允許使用new Worker的方式來開啟一個(gè)新的線程,去運(yùn)行一段單獨(dú)的js文件腳本,但是在這個(gè)新線程中嚴(yán)格的要求了可以使用的功能,比如說他只能使用ECMAScript, 不能訪問DOM和BOM。這也就限制死了多個(gè)線程同時(shí)操作DOM元素的可能。
2.使用css寫出一個(gè)三角形角標(biāo)
元素寬高設(shè)置為0,通過border屬性來設(shè)置,讓其它三個(gè)方向的border顏色為透明或者和背景色保持一致,剩余一條border的顏色設(shè)置為需要的顏色。
div?{
????width:?0;
????height:?0;
????border:?5px?solid?#transparent;
????border-top-color:?red;
}
3.水平垂直居中
我一般只使用兩種方式定位或者flex,我覺得夠用了。
div?{
????width:?100px;
????height:?100px;
????position:?absolute;
????top:?0;
????right:?0;
????bottom:?0;
????left:?0;
????margin:?auto;
}
父級控制子集居中
.parent?{
????display:?flex;
????justify-content:?center;
????align-items:?center;
}
4. css一行文本超出...
overflow:?hidden;
text-overflow:ellipsis;
white-space:?nowrap;
5.多行文本超出顯示...
display:?-webkit-box;
-webkit-box-orient:?vertical;
-webkit-line-clamp:?3;
overflow:?hidden;
6.IOS手機(jī)容器滾動(dòng)條滑動(dòng)不流暢
overflow:?auto;
-webkit-overflow-scrolling:?touch;
7.修改滾動(dòng)條樣式
隱藏div元素的滾動(dòng)條
div::-webkit-scrollbar?{
????display:?none;
}
div::-webkit-scrollbar 滾動(dòng)條整體部分
div::-webkit-scrollbar-thumb 滾動(dòng)條里面的小方塊,能向上向下移動(dòng)(或往左往右移動(dòng),取決于是垂直滾動(dòng)條還是水平滾動(dòng)條)
div::-webkit-scrollbar-track 滾動(dòng)條的軌道
div::-webkit-scrollbar-button 滾動(dòng)條的軌道的兩端按鈕,允許通過點(diǎn)擊微調(diào)小方塊的位置。
div::-webkit-scrollbar-track-piece 內(nèi)層軌道,滾動(dòng)條中間部分
div::-webkit-scrollbar-corner 邊角,即兩個(gè)滾動(dòng)條的交匯處
div::-webkit-resizer 兩個(gè)滾動(dòng)條的交匯處上用于通過拖動(dòng)調(diào)整元素大小的小控件
注意此方案有兼容性問題,一般需要隱藏滾動(dòng)條時(shí)我都是用一個(gè)色塊通過定位蓋上去,或者將子級元素調(diào)大,父級元素使用overflow-hidden截掉滾動(dòng)條部分。暴力且直接。
8.解決ios audio無法自動(dòng)播放、循環(huán)播放的問題
ios手機(jī)在使用audio或者video播放的時(shí)候,個(gè)別機(jī)型無法實(shí)現(xiàn)自動(dòng)播放,可使用下面的代碼hack。
//?解決ios?audio無法自動(dòng)播放、循環(huán)播放的問題
var?music?=?document.getElementById('video');
var?state?=?0;
document.addEventListener('touchstart',?function(){
????if(state==0){
????????music.play();
????????state=1;
????}
},?false);
document.addEventListener("WeixinJSBridgeReady",?function?()?{
????music.play();
},?false);
//循環(huán)播放
music.onended?=?function?()?{
????music.load();
????music.play();
}
9.隱藏頁面元素
display-none: 元素不會占用空間,在頁面中不顯示,子元素也不會顯示。
opacity-0: 元素透明度將為0,但元素仍然存在,綁定的事件仍舊有效仍可觸發(fā)執(zhí)行。
visibility-hidden:元素隱藏,但元素仍舊存在,占用空間,頁面中無法觸發(fā)該元素的事件。
10.前端工程化
一提到前端工程化很多人想到的都是webpack,這是不對的,webpack僅僅是前端工程化中的一環(huán)。在整個(gè)工程化過程中他幫我們解決了絕大多數(shù)的問題,但并沒有解決所有問題。
前端工程化是通過工具提升效率,降低成本的一種手段。
近些年被廣泛的關(guān)注和探討,究其原因主要是因?yàn)楝F(xiàn)代化前端應(yīng)用功能要求不斷提高,業(yè)務(wù)邏輯日益復(fù)雜,作為當(dāng)下互聯(lián)網(wǎng)時(shí)代唯一不可或缺的技術(shù),前端可以說是占據(jù)了整個(gè)開發(fā)行業(yè)的半壁江山。從傳統(tǒng)的網(wǎng)站,到現(xiàn)在的H5,移動(dòng)App,桌面應(yīng)用,以及小程序。前端技術(shù)幾乎是無所不能的全面覆蓋。
在這些表象的背后呢,實(shí)際上是行業(yè)對開發(fā)人員的要求發(fā)生了天翻地覆的變化,以往前端寫demo,套模板,調(diào)頁面這種刀耕火種的方式已經(jīng)完全不符合當(dāng)下對開發(fā)效率的要求,前端工程化就是在這樣一個(gè)背景下被提上臺面,成為前端工程師必備的手段之一。
一般來說前端工程包含,項(xiàng)目初始化,項(xiàng)目開發(fā),提交,構(gòu)建,部署,測試,監(jiān)控等流程。工程化就是以工程的角度來解決這些問題。比如項(xiàng)目初始化我們一般使用npm init, 創(chuàng)建頁面模板使用plop,我們喜歡使用ES6+開發(fā),但是需要通過babel編碼成ES5,持續(xù)集成的時(shí)候我們使用git/ci cd,但是為了保持開發(fā)規(guī)范我們引入了ESLint,部署一般使用git/cd或者jenkins等等。
11.contenteditable
html中大部分標(biāo)簽都是不可以編輯的,但是添加了contenteditable屬性之后,標(biāo)簽會變成可編輯狀態(tài)。
<div?contenteditable="true">div>
不過通過這個(gè)屬性把標(biāo)簽變?yōu)榭删庉嫚顟B(tài)后只有input事件,沒有change事件。也不能像表單一樣通過maxlength控制最大長度。我也忘記我在什么情況下用到過了,后面想起來再補(bǔ)吧。
12.calc
這是一個(gè)css屬性,我一般稱之為css表達(dá)式。可以計(jì)算css的值。最有趣的是他可以計(jì)算不同單位的差值。很好用的一個(gè)功能,缺點(diǎn)是不容易閱讀。接盤俠沒辦法一眼看出20px是啥。
div?{
????width:?calc(25%?-?20px);
}
13.Date對象
獲取當(dāng)前時(shí)間毫秒值
//?方式一
Date.now();?//?1606381881650
//?方式二
new?Date()?-?0;?//?1606381881650
//?方式三
new?Date().getTime()?//?1606381881650
創(chuàng)建Date對象的兼容性問題。
//?window和安卓支持,ios和mac不支持
new?Date('2020-11-26');?
//?window和安卓支持,ios和mac支持
new?Date('2020/11/26');
14.Proxy和Object.defineProperty區(qū)別
Proxy的意思是代理,我一般叫他攔截器,可以攔截對象上的一個(gè)操作。用法如下,通過new的方式創(chuàng)建對象,第一個(gè)參數(shù)是被攔截的對象,第二個(gè)參數(shù)是對象操作的描述。實(shí)例化后返回一個(gè)新的對象,當(dāng)我們對這個(gè)新的對象進(jìn)行操作時(shí)就會調(diào)用我們描述中對應(yīng)的方法。
new?Proxy(target,?{
????get(target,?property)?{
????},
????set(target,?property)?{
????},
????deleteProperty(target,?property)?{
????}
})
Proxy區(qū)別于Object.definedProperty。
Object.defineProperty只能監(jiān)聽到屬性的讀寫,而Proxy除讀寫外還可以監(jiān)聽屬性的刪除,方法的調(diào)用等。
通常情況下我們想要監(jiān)視數(shù)組的變化,基本要依靠重寫數(shù)組方法的方式實(shí)現(xiàn),這也是Vue的實(shí)現(xiàn)方式,而Proxy可以直接監(jiān)視數(shù)組的變化。
const?list?=?[1,?2,?3];
const?listproxy?=?new?Proxy(list,?{
????set(target,?property,?value)?{
????????target[property]?=?value;
????????return?true;?//?標(biāo)識設(shè)置成功
????}
});
list.push(4);
Proxy是以非入侵的方式監(jiān)管了對象的讀寫,而defineProperty需要按特定的方式定義對象的屬性。
15.Reflect
他是ES2015新增的對象,純靜態(tài)對象也就是不能被實(shí)例畫,只能通過靜態(tài)方法的方式調(diào)用,和Math對象類似,只能類似Math.random()的方式調(diào)用。
Reflect內(nèi)部封裝了一系列對對象的底層操作,一共14個(gè),其中1個(gè)被廢棄,還剩下13個(gè)。
Reflect的靜態(tài)方法和Proxy描述中的方法完全一致。也就是說Reflect成員方法就是Proxy處理對象的默認(rèn)實(shí)現(xiàn)。
Proxy對象默認(rèn)的方法就是調(diào)用了Reflect內(nèi)部的處理邏輯,也就是如果我們調(diào)用get方法,那么在內(nèi)部,Reflect就是將get原封不動(dòng)的交給了Reflect,如下。
const?proxy?=?new?Proxy(obj,?{
????get(target,?property)?{
????????return?Reflect.get(target,?property);
????}
})
Reflect和Proxy沒有絕對的關(guān)系,我們一般將他們兩個(gè)放在一起講是為了方便對二者的理解。
那為什么會有Reflect對象呢,其實(shí)他最大的用處就是提供了一套統(tǒng)一操作Object的API。
判斷對象是否存在某一個(gè)屬性,可以使用in操作符,但是不夠優(yōu)雅,還可以使用Reflect.has(obj, name); 刪除一個(gè)屬性可以使用delete,也可以使用Reflect.deleteProperty(obj, name); 獲取所有屬性名可以使用Object.keys, 也可以使用Reflect.ownKeys(obj); 我們更推薦使用Reflect的API來操作對象,因?yàn)樗攀俏磥怼?/p>
16.解析get參數(shù)
通過replace方法獲取url中的參數(shù)鍵值對,可以快速解析get參數(shù)。
const?q?=?{};
location.search.replace(/([^?&=]+)=([^&]+)/g,(_,k,v)=>q[k]=v);
console.log(q);?
17.解析連接url
可以通過創(chuàng)建a標(biāo)簽,給a標(biāo)簽賦值href屬性的方式,獲取到協(xié)議,pathname,origin等location對象上的屬性。
//?創(chuàng)建a標(biāo)簽
const?aEle?=?document.createElement('a');
//?給a標(biāo)簽賦值href路徑
aEle.href?=?'/test.html';
//?訪問aEle中的屬性
aEle.protocol;?//?獲取協(xié)議
aEle.pathname;?//?獲取path
aEle.origin;
aEle.host;
aEle.search;
...
18.localStorage
localStorage是H5提供的永久存儲空間,一般最大可存儲5M數(shù)據(jù),并且支持跨域隔離,他的出現(xiàn)極大提高了前端開發(fā)的可能性。localStorage的使用很多人都知道setItem,getItem,removeItem, 但他也可以直接以成員的方式操作。
//?存儲
localStorage.name?=?'yd';
//?獲取
localStorage.name;?//?yd
//?刪除
delete?localStorage.name;
//?清除全部
localStorage.clear();
//?遍歷
for?(let?i?=?0;?i?????const?key?=?localStorage.key(i);?//?獲取本地存儲的Key
????localStorage[key];?//?獲取本地存儲的value
}
localStorage滿了的情況下仍繼續(xù)存儲并不會覆蓋其他的值,而是直接報(bào)錯(cuò)(QuotaExceededError),并且當(dāng)前存儲的值也會被清空。瀏覽器支持每個(gè)域名下存儲5M數(shù)據(jù)。
19.sessionStorage
sessionStorage和localStorage的區(qū)別是,存在當(dāng)前會話,很多人理解的是瀏覽器關(guān)閉,這是不對的,假設(shè)你在A頁面存儲了sessionStorage,新開選項(xiàng)卡將A頁面的鏈接粘貼進(jìn)去打開頁面,sessionStorage也是不存在的。
所以sessionStorage存在的條件是頁面間的跳轉(zhuǎn),A頁面存儲了sessionStorage,他要通過超鏈接或者location.href或者window.open來打開另一個(gè)同域頁面才能訪問sessionStorage。
這一點(diǎn)在混合開發(fā)嵌套H5的開發(fā)模式中尤為重要,如果以新開webview的方式打開頁面,很可能sessionStorage就沒有了。
20.會話cookie
cookie在設(shè)置的時(shí)候如果不設(shè)置過期時(shí)間,就表示是個(gè)會話cookie,以前我以為關(guān)閉瀏覽器會話cookie就消失了,然而...喜提bug一個(gè)。
在多數(shù)情況下windows系統(tǒng)或者安卓系統(tǒng)確實(shí)是這樣的。但是在macOS系統(tǒng)或者ios系統(tǒng)中,關(guān)閉瀏覽器并不會清除掉會話cookie,結(jié)束瀏覽器進(jìn)程才行。
21.標(biāo)簽?zāi)0遄址?/span>
模板字符串支持在前面添加一個(gè)函數(shù),第一個(gè)參數(shù)是一個(gè)有固定內(nèi)容組成的數(shù)組,后面參數(shù)依次為傳入的變量,函數(shù)返回值為模板字符串真正展示的值。不過這個(gè)功能個(gè)人感覺沒啥用。
const?tag?=?(params,?...args)?=>?{
????return?params[0]?+?args[0];?//?返回值為模板字符串的真實(shí)值。
}
const?str?=?tag`hello?${'world'}`;
22.字符串常用的幾個(gè)方法
1. includes();
字符串中是否包含某個(gè)字符串,這個(gè)不說了,其實(shí)就是indexOf的替代方案,用起來更優(yōu)雅,
2. startsWith();
字符串是否為某個(gè)字符串開始,我一般用它判斷url是否有http
3. endsWith();
字符串是否為某個(gè)字符串結(jié)尾。判斷后綴名的時(shí)候尤其有效。
4. repeat(number);
得到一個(gè)重復(fù)number次的字符串。額...我也不知道什么時(shí)候有用,一般我用它造測試數(shù)據(jù)。
5. 'abc'.padEnd(5, '1'); // abc11;
用給定的字符串在尾部拼接到指定長度,第一個(gè)參數(shù)為長度,第二個(gè)參數(shù)為用于拼接的值。
6. 'abc'.padStart(5, '1'); // 11abc;
用給定的字符串在首部拼接到指定長度第一個(gè)參數(shù)為長度,第二個(gè)參數(shù)為用于拼接的值。首部補(bǔ)0?
23.數(shù)組快速去重
應(yīng)該很多人都知道這個(gè),數(shù)組轉(zhuǎn)換成Set, 再轉(zhuǎn)換為數(shù)組,不過這種去重方式只能去除基本數(shù)據(jù)類型組成的數(shù)組。
const?arr?=?[1,?2,?3,?4,?5,?6];
const?arr2?=?new?Set(arr);
const?arr3?=?[...arr2];
24.Object.keys, values, entries
一般我們常用Object.keys,返回一個(gè)對象的鍵組成的數(shù)組,其實(shí)還有Object.values,返回對象值組成的數(shù)組,Object.entries將對象轉(zhuǎn)成數(shù)組,每個(gè)元素是鍵值對組成的數(shù)組,可以使用此功能快速將對象轉(zhuǎn)為Map。
const?obj?=?{name:?'yd',?age:?18};
Object.keys(obj);?//?['name',?'age'];
Object.values(obj);?//?['yd',?18];
const?l?=?Object.entries(obj);?//?[['name',?'yd'],?['age':?18]];
const?m?=?new?Map(l);
25.Object.getOwnPropertyDescriptors
獲取對象的描述信息
Object.assign復(fù)制時(shí),將對象的屬性和方法當(dāng)做普通屬性來復(fù)制,并不會復(fù)制完整的描述信息,比如this。
const?p1?=?{
????a:?'y',
????b:?'d',
????get?name()?{
????????return?`${this.a}?${this.b}`;
????}
}
const?p2?=?Object.assign({},?p1);
p2.a?=?'z';
p2.name;?//?y?d;?發(fā)現(xiàn)并沒有修改p2.a的值,是因?yàn)閠his仍舊指向p1
使用Object.getOwnPropertyDescriptors獲取完整描述信息
const?description?=?Object.getOwnPropertyDescriptors(p1);
const?p2?=?Object.defineProperty({},?description);
p2.a?=?'z';
p2.name;?//?z?d
26.BigInt
JavaScript可以處理的最大數(shù)字是2的53次方?- 1,這一點(diǎn)我們可以在Number.MAX_SAFE_INTEGER中看到。
consoel.log(Number.MAX_SAFE_INTEGER);?//9007199254740991
更大的數(shù)字則無法處理,ECMAScript2020引入BigInt數(shù)據(jù)類型來解決這個(gè)問題。通過把字母n放在末尾, 可以運(yùn)算大數(shù)據(jù)。
BigInt可以使用算數(shù)運(yùn)算符進(jìn)行加、減、乘、除、余數(shù)及冪等運(yùn)算。它可以由數(shù)字和十六進(jìn)制或二進(jìn)制字符串構(gòu)造。此外它還支持AND、OR、NOT和XOR之類的按位運(yùn)算。唯一無效的位運(yùn)算是零填充右移運(yùn)算符。
const?bigNum?=?100000000000000000000000000000n;
console.log(bigNum?*?2n);?//?200000000000000000000000000000n
const?bigInt?=?BigInt(1);
console.log(bigInt);?//?1n;
const?bigInt2?=?BigInt('2222222222222222222');
console.log(bigInt2);?//?2222222222222222222n;
BigInt是一個(gè)大整數(shù),所以他不能用來存儲小數(shù)。
27.??合并空運(yùn)算符
假設(shè)變量a不存在,我們希望給系統(tǒng)一個(gè)默認(rèn)值,一般我們會使用||運(yùn)算符。但是在javascript中空字符串,0,false都會執(zhí)行||運(yùn)算符,所以ECMAScript2020引入合并空運(yùn)算符解決該問題,只允許在值為null或未定義時(shí)使用默認(rèn)值。
const?name?=?'';
console.log(name?||?'yd');?//?yd;
console.log(name????'yd');?//?'';
28.?可選鏈運(yùn)算符
業(yè)務(wù)代碼中經(jīng)常會遇到這樣的情況,a對象有個(gè)屬性b,b也是一個(gè)對象有個(gè)屬性c,
我們需要訪問c,經(jīng)常會寫成a.b.c,但是如果f不存在時(shí),就會出錯(cuò)。
const?a?=?{
????b:?{
????????c:?123,
????}
}
console.log(a.b.c);?//?123;
console.log(a.f.c);?//?f不存在所以會報(bào)錯(cuò)
ECMAScript2020定義可選鏈運(yùn)算符解決該問題,通過在.之前添加一個(gè)?將鍵名變成可選
let?person?=?{};
console.log(person?.profile?.age????18);?//?18
29.import
import是ECMAScript2015當(dāng)中定義的一套ES Module模塊系統(tǒng),語法特性絕大多數(shù)瀏覽器已經(jīng)支持了,通過給script標(biāo)簽添加type=module的屬性就可以使用ES Module的標(biāo)準(zhǔn)去執(zhí)行javascript代碼了。
<script?type="module">
console.log('this?is?es?module');
script>
在ES Module規(guī)范下,會采用嚴(yán)格模式(use strict)運(yùn)行javascript代碼。每個(gè)ES Module都運(yùn)行在單獨(dú)的作用域中,也就意味著變量間不會互相干擾。外部js文件是通過CORS的方式請求的,所以要求我們外部的js文件地址要支持跨域請求,也就是文件服務(wù)器要支持CORS。我們可以在任意網(wǎng)站控制臺輸入下面代碼。
const?script?=?document.createElement('script');
script.type?=?'module';
script.innerHTML?=?`import?React?from?'https://cdn.bootcdn.net/ajax/libs/react/17.0.1/cjs/react-jsx-dev-runtime.development.js';`;
document.body.append(script);
可以發(fā)現(xiàn)在network中請求了https://cdn.bootcdn.net/ajax/libs/react/17.0.1/cjs/react-jsx-dev-runtime.development.js資源。
ES Module的script標(biāo)簽會延遲腳本加載,等待網(wǎng)頁請求完資源之后才執(zhí)行,和使用deffer的方式加載資源相同。
需要注意的是,import {} from 'xx'導(dǎo)入模塊的時(shí)候,并不是對象的解構(gòu),而是import的固定語法,這一點(diǎn)很多人容易弄錯(cuò)。
并且ECMAScript2020中import開始支持動(dòng)態(tài)導(dǎo)入功能,在此之前import只能寫在模塊代碼的頂部,一開始就要聲明模塊依賴的其它模塊。支持動(dòng)態(tài)引入后就可以按需引入對應(yīng)的模塊,這個(gè)功能我們早在SPA中就已經(jīng)用到了。動(dòng)態(tài)導(dǎo)入返回的是一個(gè)Promise。
a.js
const?a?=?123;
export?{?a?};
b.js
import('./a.js').then(data?=>?{
????console.log(data.a);?//?123;
})
30. 0.1 + 0.2 === 0.3 // false
console.log(0.1+0.2);?//?0.30000000000000004
在JS當(dāng)中,Number類型實(shí)際上是double類型,運(yùn)算小數(shù)時(shí)存在精度問題。因?yàn)橛?jì)算機(jī)只認(rèn)識二進(jìn)制,在進(jìn)行運(yùn)算時(shí),需要將其他進(jìn)制的數(shù)值轉(zhuǎn)換成二進(jìn)制,然后再進(jìn)行計(jì)算
小數(shù)用二進(jìn)制表達(dá)時(shí)是無窮的。
//?將0.1轉(zhuǎn)換成二進(jìn)制
console.log(0.1.toString(2));?//?0.0001100110011001100110011001100110011001100110011001101
//?將0.2轉(zhuǎn)換成二進(jìn)制
console.log(0.2.toString(2));??//?0.001100110011001100110011001100110011001100110011001101
雙精度浮點(diǎn)數(shù)的小數(shù)部分最多支持53位二進(jìn)制位,所以兩者相加后,因浮點(diǎn)數(shù)小數(shù)位的限制而截?cái)嗟亩M(jìn)制數(shù)字,再轉(zhuǎn)換為十進(jìn)制,就成了0.30000000000000004,這樣在進(jìn)行算術(shù)計(jì)算時(shí)會產(chǎn)生誤差。
ES6 在Number對象上面,新增一個(gè)極小的常量Number.EPSILON。根據(jù)規(guī)格,它表示1與大于1的最小浮點(diǎn)數(shù)之間的差。對于64位浮點(diǎn)數(shù)來說,大于1的最小浮點(diǎn)數(shù)相當(dāng)于二進(jìn)制的1.00..001,小數(shù)點(diǎn)后面有連續(xù)51個(gè)零。這個(gè)值減去1之后,就等于2的-52次方。
Number.EPSILON?===?Math.pow(2,?-52)
//?true
Number.EPSILON
//?2.220446049250313e-16
Number.EPSILON.toFixed(20)
//?"0.00000000000000022204"
Number.EPSILON實(shí)際上是JavaScript能夠表示的最小精度。誤差如果小于這個(gè)值,就可以認(rèn)為已經(jīng)沒有意義了,即不存在誤差了。
引入一個(gè)這么小的量的目的,在于為浮點(diǎn)數(shù)計(jì)算,設(shè)置一個(gè)誤差范圍。我們知道浮點(diǎn)數(shù)計(jì)算是不精確的。
Number.EPSILON可以用來設(shè)置能夠接受的誤差范圍。比如,誤差范圍設(shè)為2的-50次方(即Number.EPSILON * Math.pow(2, 2)),即如果兩個(gè)浮點(diǎn)數(shù)的差小于這個(gè)值,我們就認(rèn)為這兩個(gè)浮點(diǎn)數(shù)相等。
(0.1?+?0.2?-?0.3)?Number.EPSILON?//?true
作者:隱冬
鏈接:https://juejin.cn/post/6908698827033837575
往期干貨:
?26個(gè)經(jīng)典微信小程序+35套微信小程序源碼+微信小程序合集源碼下載(免費(fèi))
?干貨~~~2021最新前端學(xué)習(xí)視頻~~速度領(lǐng)取
?前端書籍-前端290本高清pdf電子書打包下載
點(diǎn)贊和在看就是最大的支持??
