一些瑣碎的前端知識點

如何去除inline-block的間隙

描述:在html中,如果有幾個inline-block的元素并排出現(xiàn),同時他們之間有空格或者換行,那么在頁面展示中就會出現(xiàn)若干像素的間隙。html代碼如下:

// li是inline-block元素
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>

那么有什么辦法解決呢?
1.html中移除空格和換行

<ul>
    <li>1</li
    ><li>2</li
    ><li>3</li>
</ul>

或者

<ul>
    <li>1
    <li>2
    <li>3</li>
</ul>

當然這個方法的最大問題就是破壞了html的排版,不推薦

2.使用margin負值

ul li{
    display: inline-block;
    margin-left: -4px;
}

但是,inline-block的間隙在不同瀏覽器下的大小是不一致的,如圖:


不同瀏覽器下的間隙大小

因此這個方法不適合大規(guī)模使用

3.使用font-size:0

ul{
    font-size:0;
}
li{
    font-size:12px;
}

這個方法是最普遍的

4.使用letter-spacing或word-spacing

ul{
    letter-spacing:-3px;
}
li{
    letter-spacing:0;
}

這個方法也很最普遍

CSS有哪些選擇器

CSS主要有四種選擇器:

  • id選擇器
  • 類選擇器
  • 標簽選擇器
  • 偽類選擇器

基于以上四種可以組合成其他形式的選擇器,比如:

  • 后代選擇器: 父代名 后代名 { 屬性名:屬性值; }
  • 子代選擇器: 父代名>子代名 { 屬性名:屬性值; }
  • 群組選擇器: #name1, .name2, #name div { 屬性名:屬性值; }

原生ajax

var xhr
if(window.XMLHttpRequest){
    xhr = new XMLHttpRequest()
}else if(window.ActiveXObject){
    xhr = new ActiveXObject('Microsoft.XMLHTTP')
}
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
        if(xhr.status == 200){
            // ...
        }else{
            // ...
        }
    }
}
// true -> async
xhr.open('GET', url, true)
// if POST, data in send
xhr.send(null)

實現(xiàn)上拉加載,下拉刷新

要實現(xiàn)這個功能的關鍵在于頁面需要監(jiān)聽touchstarttouchmovetouchend事件,即:

// window 或 某個元素
window.addEventListner('touchmove', functinon(e){
  var touch = e.targetTouches[0]
  var x = touch.pageX
  var y = touch.pageY
  // 依據(jù)xy來決定是否執(zhí)行什么事件
})

網(wǎng)頁性能優(yōu)化有哪些呢?

其實有很多,雅虎為我們總結了性能優(yōu)化的34黃金法則,可以戳這里
能答出八條左右就夠了。

  • 減少網(wǎng)絡請求
  • 使用CDN
  • Gzip壓縮傳輸文件
  • 添加Expires or Cache-Control頭部
  • 樣式文件放入head標簽中
  • 腳本放在body標簽底部
  • 避免CSS表達式
  • 使用外部js或css文件(緩存)
  • 壓縮js或css文件
  • ...

a鏈接target

<a href="javascript:void 0;" target="_blank">鏈接</a>

在Firefox瀏覽器和IE瀏覽器下,點擊鏈接后仍然會新開一個空頁面。而在其他瀏覽器下則不會跳轉。如果禁止跳轉,則需要執(zhí)行:

e.preventDefault()

如果寫了javascript:void 0;就去掉target="_blank"

鉤子函數(shù)/程序

鉤子實際上是一個處理消息的程序段,每當特定的消息或數(shù)據(jù)發(fā)出時,在沒有到達目的程序前,鉤子會先獲得消息或數(shù)據(jù),即鉤子會先獲得控制權。這時鉤子程序可以加工處理數(shù)據(jù),也可以不作任何處理繼續(xù)傳遞消息,還可以強制結束消息的傳遞。

input與textarea的區(qū)別

在form表單中,inputtextarea是常見的輸入文本信息的輸入框。他們在功能上有很多相同地方,但是他們的最重要區(qū)別是:input無法處理自動換行,而textarea可以。即當輸入的內(nèi)容超過input的寬度時,它不會換行,而是繼續(xù)在一行中輸入。因此input不能存儲換行符,textarea可以存儲換行符。所以這決定了他們的應用場景,通常對于輸入較短的內(nèi)容時使用input,而需要輸入大段的或需要存儲換行符時,使用textarea。

表單中的input和textarea
Post提交后對數(shù)據(jù)的encode

其他不同點:
1.input標簽是自閉合的,textarea則需要成對出現(xiàn)
2.input標簽的value值放在里面,如<input name="age" value="28" id="" />
textarea標簽的內(nèi)容則是寫在標簽之間的<textarea>我是一段文本</textarea>

HTML可編輯屬性contenteditable

今天無意中看到一個面試題:使用div來模擬textarea的功能。乍看感覺有點匪夷所思,之前一直以為表單元素才是可以編輯,難道div也可以編輯嗎?原來在HTML5中提供一個全局的屬性:contenteditable。當這個屬性出現(xiàn)在一個標簽上時,瀏覽器會修改元素的部件以允許編輯。面試題考察的就是對H5新特性的使用度。
張鑫旭的一篇博文 - div模擬textarea文本域輕松實現(xiàn)高度自適應就講到了這個問題

字號與行距

用一張圖解釋兩個事物:

字號與行距

一般而言,頁面上設置字體大小以后,圖中橙色線間距也就是字體大小了。但有些字體不是這樣的,它們會比字體大小多出一些。原因是什么呢?
這需要從字體設計說起,先看一個字體的一些參數(shù):
關鍵參數(shù)

其中ascender到descender的距離就是font-size的大小。在字體設計中,有一個設計參數(shù)Units Per Em,一般為了計算比率方便,設計師會把它定位1000unit,如下圖所示:
image.png

那么一般ascender到descender的距離為1000才是合理,但是有時候設計師就會設計的比1000大,相應,它就會被撐開。
比如,ascender - descender = 1200font-size: 20px,那么它的實際大小是1200/1000 * 20 = 24px

字體的大小問題,就可以解釋了頁面上有的元素莫名其妙被撐開了。
原文地址

<==================華麗的分割線========================>

Blob對象

一個 Blob對象表示一個不可變的, 原始數(shù)據(jù)的類似文件對象。Blob表示的數(shù)據(jù)不一定是一個JavaScript原生格式。 File 接口基于Blob,繼承 blob功能并將其擴展為支持用戶系統(tǒng)上的文件。

定義上說File對象的基礎是Blob對象,即接受Blob對象的APIs也被列在 File文檔中。

從Blob中讀取內(nèi)容的唯一方法是使用 FileReader。以下代碼將 Blob 的內(nèi)容作為類型數(shù)組讀取:

var reader = new FileReader();
reader.addEventListener("loadend", function() {
   // reader.result contains the contents of blob as a typed array
});
reader.readAsArrayBuffer(blob);

<==================華麗的分割線========================>

解釋器執(zhí)行代碼時的違描述

1.尋找調(diào)用函數(shù)的代碼
2.在執(zhí)行函數(shù)代碼前,創(chuàng)建執(zhí)行上下文
3.進入創(chuàng)建階段

  • 初始化作用域鏈
  • 創(chuàng)建變量對象
    創(chuàng)建參數(shù)對象,檢查參數(shù)的上下文,初始化其名稱和值并創(chuàng)建一個引用拷貝
  • 掃描上下文中的函數(shù)聲明
    對于每個被發(fā)現(xiàn)的函數(shù),在變量對象中創(chuàng)建一個和函數(shù)名同名的屬性,這是函數(shù)在內(nèi)存中的引用
    如果函數(shù)名已經(jīng)存在,引用會被覆蓋
  • 掃描上下文中的變量聲明
    對于每個被發(fā)現(xiàn)的變量聲明,在變量對象中創(chuàng)建一個同名屬性并初始化至為undefined
    如果變量名在變量對象中已經(jīng)存在,什么都不做,繼續(xù)掃描

4.確定上下文中的"this"
5.即獲/代買執(zhí)行階段

  • 執(zhí)行/在上下文中解釋函數(shù)代碼,并在代碼逐行執(zhí)行時給變量賦值

看個例子:

function foo(i) {
    var a = 'hello';
    var b = function privateB() {

    };
    function c() {

    }
}

foo(22);

在調(diào)用foo(22),創(chuàng)建階段看起來像是這樣:

fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: undefined,
        b: undefined
    },
    this: { ... }
}

你可以發(fā)現(xiàn), 創(chuàng)建階段 掌管著屬性名的定義,而不是給它們賦值,不過參數(shù)除外。 一旦 創(chuàng)建階段 完成之后,執(zhí)行流就會進入函數(shù)中。 在函數(shù)執(zhí)行完之后,激活 / 代碼 執(zhí)行階段 看起來像是這樣:

fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: 'hello',
        b: pointer to function privateB()
    },
    this: { ... }
}

<==================華麗的分割線========================>

localStorage的一些用法

原文地址:http://mp.weixin.qq.com/s/vy7pRk97T7SN7Jc-uI_smQ
1.存儲一些持久化的數(shù)據(jù)(基本用法)
2.緩存靜態(tài)文件(比較復雜,不太推薦)
3.同源窗口通信(同源窗口監(jiān)聽storage事件等)
4.作為前端DB的存儲介質(zhì)
5.表單自動持久化

<==================華麗的分割線========================>

new關鍵詞干了些什么

1.聲明一個中間對象;
2.將該中間對象的原型指向構造函數(shù)的原型;
3.將構造函數(shù)的this,指向該中間對象;
4.返回該中間對象,即返回實例對象。

偽代碼

// 先一本正經(jīng)的創(chuàng)建一個構造函數(shù),其實該函數(shù)與普通函數(shù)并無區(qū)別
var Person = function(name, age) {
    this.name = name;
    this.age = age;
    this.getName = function() {
        return this.name;
    }
}

// 將構造函數(shù)以參數(shù)形式傳入
function New(func) {

    // 聲明一個中間對象,該對象為最終返回的實例
    var res = {};
    if (func.prototype !== null) {

        // 將實例的原型指向構造函數(shù)的原型
        res.__proto__ = func.prototype;
    }

    // ret為構造函數(shù)執(zhí)行的結果,這里通過apply,將構造函數(shù)內(nèi)部的this指向修改為指向res,即為實例對象
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));

    // 當我們在構造函數(shù)中明確指定了返回對象時,那么new的執(zhí)行結果就是該返回對象
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }

    // 如果沒有明確指定返回對象,則默認返回res,這個res就是實例對象
    return res;
}

// 通過new聲明創(chuàng)建實例,這里的p1,實際接收的正是new中返回的res
var p1 = New(Person, 'tom', 20);
console.log(p1.getName());

// 當然,這里也可以判斷出實例的類型了
console.log(p1 instanceof Person); // true

<==================華麗的分割線========================>

ES6箭頭函數(shù)

  • 不綁定自己的this、arguments、super或new.target
  • 不綁定arguments,即在箭頭函數(shù)體中無法通過arguments讀取到自己的參數(shù),它僅僅是最近封閉范圍內(nèi)引用相同的名稱
  • 箭頭函數(shù)沒有prototype屬性
  • 箭頭函數(shù)中,this
    是根據(jù)當前的詞法作用域來決定的,就是說,箭頭函數(shù)會繼承外層函數(shù)調(diào)用的this
    綁定(無論this綁定到什么)

為了有意外事情發(fā)生,請忘記箭頭函數(shù)有this和arguments

<==================華麗的分割線========================>

void

void運算符 對給定的表達式進行求值,然后返回underfined
主要用途:
1.返回undefiend
經(jīng)常在JS代碼中獲得全局變量undefined,就可以用void(0)

void(0) === undefined

2.Javascript URIs
當用戶點擊一個以javascriot:URI時,瀏覽器會對冒號后面的代碼求值,然后把求值結果顯示在頁面上,這時頁面基本上是一大片空白,這通常不是我們想要的。只有當返回結果是undefined時,瀏覽器才不會做這件傻事。于是我們用void(0)來實現(xiàn)這個需求。

<a href="javascript:void(0);"></a>

//推薦使用, 少幾個字符嘛
<a href="javascript:;"></a>

<==================華麗的分割線========================>

RESTful架構

Representational State Transfer
1.每個URI定位一種資源;
2.客戶端與服務器之間以某種表現(xiàn)形式傳遞資源;
3.客戶端通過HTTP的四個動詞(GET,POST,PUT,DELETE)對服務器端資源進行操作,實現(xiàn)表現(xiàn)層狀態(tài)轉化

符合以上標準的架構可以認為是RESTful架構

誤區(qū):
1.由于URI是用于定位一種資源,可以認為是資源的唯一標識,因此設計URI時,不應該出現(xiàn)動詞;
2.對資源的限定條件,應該以search形式追加到URI中,如:api.xxx.com/imgs?size=1000&limit=10
3.對資源表現(xiàn)層的限定,也可以在請求報文頭部信息中說明:

accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

<==================華麗的分割線========================>

attribute 與 property

attribute 與 property 都可以叫“特性”,也都可以叫“屬性”

區(qū)別:
從 HTML 到 DOM 元素,一種是聲明式的語言,一種是命令式語言。attribute 是直接收集 HTML 中的屬性轉為 js 對象,對象的 value 最接近原生態(tài),也就是 HTML 標記里面的樣子;property 也是轉為 js 對象,但是轉化的過程中會對 value 做一些處理,將 value 轉為對 js 來說更有意義的值。
如:

<input type="checkbox" checked="checked" />

elem.getAttribute("checked”) // “checked”,原生態(tài)的值
elem.checked // true,對 js 來說更有意義的值

<==================華麗的分割線========================>

babel轉es6至es5在IE8下運行有bug

關于default的問題:
由于 IE8 中不支持 default 做 key,這個暫時無解。
不過你暫時可以這樣,不使用 export default,改用傳統(tǒng)的 module.exports =。
引用時使用 import 或 require 均可

<==================華麗的分割線========================>

es5-shim 與 es5-sham的區(qū)別

shim: ES5中有的方法可以通過其他舊的JS代碼模擬出來,那么shim的作用就是用ES3的代碼去實現(xiàn)ES5中才有API。
如數(shù)組中的一些方法就可以完美模擬,(forEach, indexOf, some等)

sham: 當然有些ES5的API用ES3代碼不能完美模擬出來,因此sham盡量模擬出來,起碼不會有致命錯誤。但是最后結果對不對,那就管不著了。
如Object中的一些方法,如Object.creat, Object.defineProperty.

具體有哪些可以訪問這里

那么引申出另一個問題,shim與polyfill有什么區(qū)別呢?
shim在英文中意思是硬墊片(鐵的或者木頭的),而polyfill在英文中意思是軟墊片(棉花或聚酯類)
引申到JS中:
shim在舊瀏覽器中以強硬的手段模擬行為,比如jQuery的ajax,就是將XHR和ActiveXObject整合一起,這樣保證在瀏覽器中請求行為是一致的。因此shim不會遵循標準,而是自己實現(xiàn)的
polyfill則是在舊瀏覽器中使用ActiveXObject模擬出window.XMLHttpRequest,盡量保持和標準一致

持續(xù)更新中...

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • 原文: https://github.com/ecomfe/spec/blob/master/javascript...
    zock閱讀 3,408評論 2 36
  • 美國costco第二大超市要來中國了 中國是一個很大的市場,世界各國的人們都可以來投資、創(chuàng)業(yè)。不僅帶來了新的思想、...
    子畫畫閱讀 2,184評論 3 0
  • 今天讀書讀到香菱學詩一章,不禁感嘆她就是這本書中最閃亮的女子,富貴小姐從丟失到販賣,期間受盡痛苦折磨自不必說,然而...
    蝴蝶王妃閱讀 382評論 0 5