一年前寫了一篇JavaScript八張思惟導圖,主要是對前端JavaScript知識點的一個系統的整理和總結。本篇文章用了近一個月時間,蒐集整理了網上各類面試筆試題及本人針對前端的一些理解以及各路大神針對前端難點部分的詳細介紹,能夠做爲之後面試或者考察面試人員的參考。 相信經過這兩篇文章的學習,必定會讓你對前端有一個更深的認識。javascript
後續會持續更新......css
string number boolean undefined nullhtml
typeof null === 'object' // true
typeof undefined === 'undefined' // true
==比較以前會先進行類型轉換,即不會對類型進行比較。例如:前端
12 == '12' // true
true == 1 // true
false == '0' // true
複製代碼
===會比較數值和類型。例如:vue
12 === '12' // false
12 === 12 // true
true === 1 // false
false === '0' // false
複製代碼
JS在使用運算符號或者對比符時,會自帶隱式轉換,規則以下:java
-、*、/、% :一概轉換成數值後計算node
+:jquery
[1].toString() === '1'nginx
{}.toString() === '[object object]'git
NaN !== NaN 、+undefined 爲 NaN
"Attribute"是在HTML中定義的,而"property"是在DOM上定義的。爲了說明區別,假設咱們在HTML中有一個文本框:
<input type="text" value="Hello">
const input = document.querySelector('input');
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello
複製代碼
可是在文本框中鍵入「 World!」後:
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello World!
複製代碼
定義: 全局屬性 NaN 的值表示不是一個數字(Not-A-Number)
如何判斷一個值是不是NaN: 等號運算符(== 和 ===) 不能被用來判斷一個值是不是 NaN。必須使用 Number.isNaN() 或 isNaN() 函數。
NaN === NaN; // false
Number.NaN === NaN; // false
isNaN(NaN); // true
isNaN(Number.NaN); // true
複製代碼
須要考慮三個問題:
檢查對象的「值相等」的一個強大的方法,最好是依靠完善的測試庫,涵蓋了各類邊界狀況。Underscore和Lo-Dash有一個名爲_.isEqual()方法,用來比較好的處理深度對象的比較。您可使用它們像這樣:
// Outputs: true
console.log(_.isEqual(obj1, obj2));
複製代碼
'use strict' 是用於對整個腳本或單個函數啓用嚴格模式的語句。嚴格模式是可選擇的一個限制 JavaScript 的變體一種方式 。
優勢:
缺點:
總的來講,我認爲利大於弊,我歷來不使用嚴格模式禁用的功能,所以我推薦使用嚴格模式。
.call和.apply都用於調用函數,第一個參數將用做函數內 this 的值。然而,.call接受逗號分隔的參數做爲後面的參數,而.apply接受一個參數數組做爲後面的參數。一個簡單的記憶方法是,從call中的 C 聯想到逗號分隔(comma-separated),從apply中的 A 聯想到數組(array)。
function add(a, b) {
return a + b;
}
console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3
複製代碼
.call和.apply是當即執行的, .bind 返回函數的副本,但帶有綁定上下文!它不是當即執行的。
const person = { name: 'Lydia' }
function sayHi(age) {
console.log(`${this.name} is ${age}`)
}
sayHi.call(person, 21)
sayHi.bind(person, 21)
結果: Lydia is 21 function
複製代碼
摘自MDN:
bind()方法建立一個新的函數, 當被調用時,將其 this 關鍵字設置爲提供的值,在調用新函數時,在任何提供以前提供一個給定的參數序列。
根據個人經驗,將this的值綁定到想要傳遞給其餘函數的類的方法中是很是有用的。在 React 組件中常常這樣作。
var arr = [];
if (Array.isArray(arr) && arr.length === 0) {
console.log('是空數組');
}
// Array.isArray是ES5提供的,若是不支持。用下面的方案。
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
複製代碼
數組亂序:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(function () {
return Math.random() - 0.5;
});
複製代碼
數組拆解:
// flat: [1,[2,3]] --> [1, 2, 3]
Array.prototype.flat = function() {
return this.toString().split(',').map(item => +item )
}
複製代碼
以上4種操做均會改變數組自己
map用法:
let array = [1, 2, 3, 4, 5];
let newArray = array.map((item, i, arr) => {
return item * 2;
});
console.log("array:", array); // [1, 2, 3, 4, 5]
console.log("newArray:", newArray); // [2, 4, 6, 8, 10]
// 此處的array接受map方法運算以後的返回值
// 可是map方法並不能改變原來的數組
複製代碼
forEach用法:
let array = [1, 2, 3, 4, 5];
let newArray = array.forEach((item, i, arr) => {
console.log('item:' + item + ', index:' + i);
// array[i] = item * 2; // 能夠用這種方式改變原始數組的值
});
console.log("array:", array); // [1, 2, 3, 4, 5]
console.log("newArray:", newArray); // undefined
// forEach方法沒有返回值
複製代碼
Object.prototype.hasOwnProperty()
複製代碼
for循環
for (let property in obj) {
console.log(property);
}
複製代碼
可是,這還會遍歷到它的繼承屬性,在使用以前,你須要加入obj.hasOwnProperty(property)檢查。
Object.keys()
Object.keys(obj).forEach((property) => { ... })
複製代碼
Object.keys()方法會返回一個由一個給定對象的自身可枚舉屬性組成的數組。
Object.getOwnPropertyNames()
Object.getOwnPropertyNames(obj).forEach((property) => { ... })
複製代碼
Object.getOwnPropertyNames()方法返回一個由指定對象的全部自身屬性的屬性名(包括不可枚舉屬性但不包括 Symbol 值做爲名稱的屬性)組成的數組。
for loops
for (let i = 0; i < arr.length; i++) { ... }
複製代碼
forEach
arr.forEach((item, index, arr) { ... })
複製代碼
map
arr.map((item, index, arr) => { ... })
複製代碼
匿名函數能夠在 IIFE 中使用,來封裝局部做用域內的代碼,以便其聲明的變量不會暴露到全局做用域。
(function() {
// 一些代碼。
})();
複製代碼
匿名函數能夠做爲只用一次,不須要在其餘地方使用的回調函數。當處理函數在調用它們的程序內部被定義時,代碼具備更好地自閉性和可讀性,能夠省去尋找該處理函數的函數體位置的麻煩。
setTimeout(function() {
console.log('Hello world!');
}, 1000);
複製代碼
匿名函數能夠用於函數式編程或 Lodash(相似於回調函數)。
const arr = [1, 2, 3];
const double = arr.map(function(el) {
return el * 2;
});
console.log(double); // [2, 4, 6]
複製代碼
IIFE( 當即調用函數表達式)是一個在定義時就會當即執行的 JavaScript 函數。
(function () {
statements
})();
複製代碼
這是一個被稱爲 自執行匿名函數 的設計模式,主要包含兩部分。第一部分是包圍在 圓括號運算符 () 裏的一個匿名函數,這個匿名函數擁有獨立的詞法做用域。這不只避免了外界訪問此 IIFE 中的變量,並且又不會污染全局做用域。
第二部分再一次使用 () 建立了一個當即執行函數表達式,JavaScript 引擎到此將直接執行函數。
當初始的 HTML 文檔被徹底加載和解析完成以後,DOMContentLoaded事件被觸發,而無需等待樣式表、圖像和子框架的完成加載。
window的load事件僅在 DOM 和全部相關資源所有完成加載後纔會觸發。
下面將對以下數據進行判斷它們的類型
var bool = true
var num = 1
var str = 'abc'
var und = undefined
var nul = null
var arr = [1, 2, 3]
var obj = {a: 'aa', b: 'bb'}
var fun = function() {console.log('I am a function')}
複製代碼
typeof: 適合基本的數據類型和函數
console.log(typeof bool); // boolean
console.log(typeof num); // number
console.log(typeof str); // string
console.log(typeof und); // undefined
console.log(typeof nul); // object
console.log(typeof arr); // object
console.log(typeof obj); // object
console.log(typeof fun); // function
複製代碼
由結果可知typeof能夠測試出number、string、boolean、undefined及function,而對於null及數組、對象,typeof均檢測出爲object,不能進一步判斷它們的類型。
instanceof: 判斷對象類型,基於原型鏈去判斷。
obj instanceof Object: 左操做數是一個對象,右操做數是一個函數構造器或者函數對象,判斷左邊的操做數的原型鏈_proto_屬性是否有右邊這個函數對象的proptotype屬性。
console.log(bool instanceof Boolean);// false
console.log(num instanceof Number); // false
console.log(str instanceof String); // false
console.log(und instanceof Object); // false
console.log(arr instanceof Array); // true
console.log(nul instanceof Object); // false
console.log(obj instanceof Object); // true
console.log(fun instanceof Function);// true
var bool2 = new Boolean()
console.log(bool2 instanceof Boolean);// true
var num2 = new Number()
console.log(num2 instanceof Number);// true
var str2 = new String()
console.log(str2 instanceof String);// true
function Animation(){}
var ani = new Animation()
console.log(ani instanceof Animation);// true
function Dog(){}
Dog.prototype = new Animation()
var dog = new Dog()
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animation);// true
console.log(dog instanceof Object); // true
複製代碼
從結果中看出instanceof不能區別undefined和null,並且對於基本類型若是不是用new聲明的則也測試不出來,對因而使用new聲明的類型,它還能夠檢測出多層繼承關係。
constructor: 返回對建立此對象的函數的引用
console.log(bool.constructor === Boolean); // true
console.log(num.constructor === Number); // true
console.log(str.constructor === String); // true
console.log(arr.constructor === Array); // true
console.log(obj.constructor === Object); // true
console.log(fun.constructor === Function); // true
console.log(ani.constructor === Animation); // true
console.log(dog.constructor === Dog); // false
console.log(dog.constructor === Animation);// true
複製代碼
null 和 undefined 是無效的對象,所以是不會有 constructor 存在的,這兩種類型的數據須要經過其餘方式來判斷。
函數的 constructor 是不穩定的,這個主要體如今自定義對象上,當開發者重寫 prototype 後,原有的 constructor 引用會丟失。因此dog.constructor === Animation 而不是 Dog
Object.prototype.toString.call
console.log(Object.prototype.toString.call(bool)); //[object Boolean]
console.log(Object.prototype.toString.call(num)); //[object Number]
console.log(Object.prototype.toString.call(str)); //[object String]
console.log(Object.prototype.toString.call(und)); //[object Undefined]
console.log(Object.prototype.toString.call(nul)); //[object Null]
console.log(Object.prototype.toString.call(arr)); //[object Array]
console.log(Object.prototype.toString.call(obj)); //[object Object]
console.log(Object.prototype.toString.call(fun)); //[object Function]
console.log(Object.prototype.toString.call(dog)); //[object Object]
複製代碼
原理(摘自高級程序設計3):在任何值上調用 Object 原生的 toString() 方法,都會返回一個 [object NativeConstructorName] 格式的字符串。每一個類在內部都有一個 [[Class]] 屬性,這個屬性中就指定了上述字符串中的構造函數名。 可是它不能檢測非原生構造函數的構造函數名。
使用jquery中的$.type
console.log($.type(bool)); //boolean
console.log($.type(num)); //number
console.log($.type(str)); //string
console.log($.type(und)); //undefined
console.log($.type(nul)); //null
console.log($.type(arr)); //array
console.log($.type(obj)); //object
console.log($.type(fun)); //function
console.log($.type(dog)); //object
複製代碼
$.type()內部原理就是用的Object.prototype.toString.call()
添加操做
let element = document.createElement("div"); // 建立元素
body.appendChild(element); // 將一個節點添加到指定父節點的子節點列表末尾
複製代碼
刪除操做
var oldChild = node.removeChild(child); // 刪除子元素
ChildNode.remove() // 刪除元素
複製代碼
修改操做
Node.innerText // 修改元素文本內容
Element.innerHTML // 設置或獲取描述元素後代的HTML語句
複製代碼
查找操做
Document.getElementById() // 返回對擁有指定 id 的第一個對象的引用
Document.querySelector() // 返回文檔中匹配指定的CSS選擇器的第一元素
Document.querySelectorAll() // 返回與指定的選擇器組匹配的文檔中的元素列表
複製代碼
瀏覽器下載除JS外的資源時,會並行下載,以提升性能。但下載JS腳本時,會禁止並行下載(稱爲腳本阻塞Scripts Block Downloads)。瀏覽器遇到JS時,必須等JS下載,解析,執行完後,才能繼續並行下載下一個資源。緣由是JS可能會改變頁面或改變JS間的依賴關係,例如A.js中用document.write改變頁面,B.js依賴於A.js。所以要嚴格保證順序,不能並行下載。
因爲瀏覽器在遇到<body>標籤前是不會渲染頁面的,爲了不白屏,一般的建議是將JS放到標籤底下,能夠有最佳的用戶體驗。
按推薦度排序:
動態建立<script>標籤(Dynamic Script Element)
var script = document.createElement('script'); // 建立script標籤
script.type = "text/javascript";
script.src = "A.js";
document.getElementsByTagName('head')[0].appendChild(script); // 塞進頁面
複製代碼
先用document.createElement(‘script’)生成一個script標籤,再設置它的src屬性,最後將其插入到<head>中。
script標籤被插入到頁面的DOM樹後,就會開始下載src屬性指定的腳本。並且經過動態腳本元素下載腳本是異步的,不會阻塞頁面的其餘下載和處理過程,所以script標籤插入<head>中也沒問題。
Script async
<script type="text/javascript" src="A.js" async></script>
複製代碼
瀏覽器解析到HTML裏的該行script標籤,發現指定爲async,會異步下載解析執行腳本。
async 是HTML5裏爲script標籤新增的屬性,對於低版本瀏覽器會存在兼容性問題。
它會在下載完成後馬上執行,而不是會等到DOM加載完成以後再執行,因此仍是有可能會形成阻塞。
這種方式只適用於引用外部js文件的<script>標籤。
添加async屬性的js文件不該該使用document.write方法。
對多個帶有async的js文件,它不能保證按順序執行,它是哪一個js文件先下載完就先執行哪一個。
Script defer
<script type="text/javascript" src="A.js" defer></script>
複製代碼
瀏覽器解析到HTML裏的該行script標籤,發現指定爲defer,會暫緩下載解析執行腳本。而是等到頁面加載完畢後,才加載腳本(更精確地說,是在DOM樹構建完成後,在window.onload觸發前,加載defer的腳本)。
defer也是隻適用於外部js文件,也不能在js中使用document.write方法。
能夠保證多個js文件的執行順序就是它們在頁面中出現的順序。
經過判斷Global對象是否爲window,若是不爲window,則當前腳本運行在node.js環境中。
this === window ? 'browser' : 'node';
複製代碼
基礎數據類型與棧內存
JS中的基礎數據類型,這些值都有固定的大小,每每都保存在棧內存中,由系統自動分配存儲空間。咱們能夠直接操做保存在棧內存空間的值,所以基礎數據類型都是按值訪問。
數據在棧內存中的存儲與使用方式相似於數據結構中的堆棧數據結構,遵循後進先出的原則。
基礎數據類型: Number String Null Undefined Boolean
引用數據類型與堆內存
與其餘語言不一樣,JS的引用數據類型,好比數組Array、對象Object、函數Function,它們值的大小是不固定的。引用數據類型的值是保存在堆內存中的對象。JavaScript不容許直接訪問堆內存中的位置,所以咱們不能直接操做對象的堆內存空間。
在操做對象時,其實是在操做對象的引用而不是實際的對象。所以,引用類型的值都是按引用訪問的。這裏的引用,咱們能夠粗淺地理解爲保存在棧內存中的一個地址,該地址與堆內存的實際值相關聯。
總結:
棧內存 | 堆內存 |
---|---|
存儲基礎數據類型 | 存儲引用數據類型 |
按值訪問 | 按引用訪問 |
存儲的值大小固定 | 存儲的值大小不定,可動態調整 |
由系統自動分配內存空間 | 由開發人員經過代碼分配 |
主要用來執行程序 | 主要用來存放對象 |
空間小,運行效率高 | 空間大,可是運行效率相對較低 |
先進後出,後進先出 | 無序存儲,可根據引用直接獲取 |
防抖與節流函數是一種最經常使用的 高頻觸發優化方式,能對性能有較大的幫助。
防抖 (debounce): 將屢次高頻操做優化爲只在最後一次執行,一般使用的場景是:用戶輸入,只需再輸入完成後作一次輸入校驗便可。
節流(throttle): 每隔一段時間後執行一次,也就是下降頻率,將高頻操做優化成低頻操做,一般使用場景: 滾動條事件 或者 resize 事件,一般每隔 100~500 ms執行一次便可。
function throttle(method, context) {
clearTimeout(method.tID);
method.tID = setTimeout(function () {
method.call(context);
}, 1000);
}
複製代碼
用法:
function showTime() {
console.log("nowDate:" + new Date().toLocaleDateString());
}
setInterval(function () {
throttle(showTime);
}, 2000);
複製代碼
模塊化開發在現代開發中已經是必不可少的一部分,它大大提升了項目的可維護、可拓展和可協做性。一般,咱們 在瀏覽器中使用 ES6 的模塊化支持,在 Node 中使用 commonjs 的模塊化支持。
分類:
require與import的區別
單頁Web應用(single page web application,SPA),就是隻有一張Web頁面的應用,是加載單個HTML 頁面並在用戶與應用程序交互時動態更新該頁面的Web應用程序。
單頁應用SPA | 多頁應用MPA | |
---|---|---|
組成 | 一個外殼頁面和多個頁面片斷組成 | 多個完整頁面構成 |
資源共用(css,js) | 共用,只需在外殼部分加載 | 不共用,每一個頁面都須要加載 |
刷新方式 | 頁面局部刷新或更改 | 整頁刷新 |
url 模式 | a.com/#/pageone a.com/#/pagetwo |
a.com/pageone.html a.com/pagetwo.html |
用戶體驗 | 頁面片斷間的切換快,用戶體驗良好 因爲要一次加載全部的資源(html/js),故首屏加載慢 |
頁面切換加載緩慢,流暢度不夠,用戶體驗比較差 首屏加載很快 |
轉場動畫 | 容易實現 | 沒法實現 |
數據傳遞 | 容易 | 依賴 url傳參、或者cookie 、localStorage等 |
搜索引擎優化(SEO) | 須要單獨方案、實現較爲困難、不利於SEO檢索。 Prerender預渲染優化SEO |
實現方法簡易 |
試用範圍 | 高要求的體驗度、追求界面流暢的應用 | 適用於追求高度支持搜索引擎的應用 |
開發成本 | 較高,常需藉助專業的框架 | 較低,但頁面重複代碼多 |
維護成本 | 相對容易 | 相對複雜 |
如下是移動端的優化方案,大部分Web端也一樣適用
事件循環是指: 執行一個宏任務,而後執行清空微任務列表,循環再執行宏任務,再清微任務列表
功能檢測(feature detection)
功能檢測包括肯定瀏覽器是否支持某段代碼,以及是否運行不一樣的代碼(取決於它是否執行),以便瀏覽器始終可以正常運行代碼功能,而不會在某些瀏覽器中出現崩潰和錯誤。例如:
if ('geolocation' in navigator) {
// 可使用 navigator.geolocation
} else {
// 處理 navigator.geolocation 功能缺失
}
複製代碼
Modernizr是處理功能檢測的優秀工具。
功能推斷(feature inference)
功能推斷與功能檢測同樣,會對功能可用性進行檢查,可是在判斷經過後,還會使用其餘功能,由於它假設其餘功能也可用,例如:
if (document.getElementsByTagName) {
element = document.getElementById(id);
}
複製代碼
很是不推薦這種方式。功能檢測更能保證萬無一失。
UA 字符串
這是一個瀏覽器報告的字符串,它容許網絡協議對等方(network protocol peers)識別請求用戶代理的應用類型、操做系統、應用供應商和應用版本。它能夠經過navigator.userAgent訪問。 然而,這個字符串很難解析而且極可能存在欺騙性。例如,Chrome 會同時做爲 Chrome 和 Safari 進行報告。所以,要檢測 Safari,除了檢查 Safari 字符串,還要檢查是否存在 Chrome 字符串。不要使用這種方式。
考慮到歷史緣由及現代瀏覽器中用戶代理字符串(userAgent)的使用方式,經過用戶代理字符串來檢測特定的瀏覽器並非一件輕鬆的事情。因此使用用戶代理檢測是最後的選擇。
用戶代理檢測通常適用如下的情形:
可使用navigator.userAgent。
同源策略限制了從同一個源加載的文檔或腳本如何與來自另外一個源的資源進行交互。這是一個用於隔離潛在惡意文件的重要安全機制。
下表給出了相對http://store.company.com/dir/page.html同源檢測的示例:
URL | 結果 | 緣由 |
---|---|---|
store.company.com/dir2/other.… | 成功 | 只有路徑不一樣 |
store.company.com/dir/inner/a… | 成功 | 只有路徑不一樣 |
store.company.com/secure.html | 失敗 | 不一樣協議 ( https和http ) |
store.company.com:81/dir/etc.htm… | 失敗 | 不一樣端口 ( http:// 80是默認的) |
news.company.com/dir/other.h… | 失敗 | 不一樣域名 ( news和store ) |
不一樣標籤頁間的通信,本質原理就是去運用一些能夠 共享的中間介質,所以比較經常使用的有如下方法:
按實際使用量排序(我的理解):
CORS 跨域
nginx反向代理
WebSockets
JSONP 只支持GET請求
hash + iframe 只支持GET請求
postMessage 只支持GET請求
document.domain
目前常見的存儲方式爲如下三種:
在H5出現以前,數據都是存儲在cookie中的。爲了解決cookie的侷限性引入了Web存儲,indexedDB用於客戶端存儲大量結構化數據(包括, 文件/ blobs)。
共同點:都是保存在瀏覽器端、且同源的
區別:
Cookie | localStorage | sessionStorage | indexedDB | |
---|---|---|---|---|
容量大小 | 4kb左右 | 5M左右 | 5M左右 | 無限容量 |
過時時間 | 只在設置的過時時間以前一直有效, 即便窗口或者瀏覽器關閉 |
始終有效 | 當前瀏覽器窗口關閉前有效 | 始終有效 |
存儲方式 | 瀏覽器和服務器間來回傳遞 | 本地保存 | 本地保存 | 本地保存 |
做用域 | 在同源窗口中共享 | 在同源窗口中共享 | 在同源窗口而且同一窗口中共享 | 在同源窗口中共享 |
XSS(跨站腳本攻擊)幾種形式,防範手段,過濾哪些字符
csrf(跨站請求僞造)原理,實現,防範手段
sql注入
命令行注入
DDoS(Distributed Denial of Service) 又叫分佈式拒絕服務
流量劫持 DNS劫持 HTTP劫持
服務器漏洞
現代瀏覽器爲JavaScript創造的 多線程環境。能夠新建並將部分任務分配到worker線程並行運行,兩個線程可 獨立運行,互不干擾,可經過自帶的 消息機制 相互通訊。
限制:
可用 chrome 中的 timeline 進行內存標記,可視化查看內存的變化狀況,找出異常點。
lidaguang1989.github.io/2018/01/jav…
function myTrim(str) {
let reg = /^\s+|\s+$/g;
return str.replace(reg, "");
}
console.log(myTrim(' asdf '));
複製代碼
link > visited > hover > active
content 屬性專門應用在 before/after 僞元素上,用於插入額外內容或樣式。可減小標籤的使用。
僞元素 -- 在內容元素的先後插入額外的元素或樣式,可是這些元素實際上並不在文檔中生成。
它們只在外部顯示可見,但不會在文檔的源代碼中找到它們,所以,稱爲「僞」元素。例如:
p::before {content:"第一章:";}
p::after {content:"Hot!";}
p::first-line {background:red;}
p::first-letter {font-size:30px;}
複製代碼
僞類 -- 將特殊的效果添加到特定選擇器上。它是已有元素上添加類別的,不會產生新的元素。例如: a:hover {color: #FF00FF} p:first-child {color: red}
瀏覽器的默認字體都是16px,那麼1em=16px,以此類推計算10px=0.625em
爲了簡化font-size的換算,通常都會在body中寫入如下代碼
body { font-size: 62.5%; } /* 公式16px*62.5%=10px */
複製代碼
em的值並非固定的
em會繼承父級元素的字體大小(參考物是父元素的font-size)
em中全部的字體都是相對於父元素的大小決定的;因此若是一個設置了font-size:1.2em的元素在另外一個設置了font-size:1.2em的元素裏,而這個元素又在另外一個設置了font-size:1.2em的元素裏,那麼最後計算的結果是1.2X1.2X1.2=1.728em
頁面渲染時,dom 元素所採用的 佈局模型。可經過box-sizing進行設置。
默認值,標準盒子模型。 width 與 height 只包括內容的寬和高, 不包括邊框(border),內邊距(padding),外邊距(margin)。注意: 內邊距、邊框和外邊距都在這個盒子的外部。 好比說,.box {width: 350px; border: 10px solid black;} 在瀏覽器中的渲染的實際寬度將是 370px。
尺寸計算公式:
width = 內容的寬度
height = 內容的高度
寬度和高度的計算值都不包含內容的邊框(border)和內邊距(padding)。
width 和 height 屬性包括內容,內邊距和邊框,但不包括外邊距。這是當文檔處於 Quirks模式 時Internet Explorer使用的盒模型。注意,填充和邊框將在盒子內 , 例如, .box {width: 350px; border: 10px solid black;} 致使在瀏覽器中呈現的寬度爲350px的盒子。內容框不能爲負,而且被分配到0,使得不可能使用border-box使元素消失。
尺寸計算公式:
width = border + padding + 內容的寬度
height = border + padding + 內容的高度
通過定位的元素,其position屬性值必然是relative、absolute、fixed或sticky。
block | inline-block | inline | |
---|---|---|---|
大小 | 填充其父容器的寬度 | 取決於內容 | 取決於內容 |
定位 | 重新的一行開始,而且不容許旁邊有 HTML 元素(除非是float) | 與其餘內容一塊兒流動,並容許旁邊有其餘元素 | 與其餘內容一塊兒流動,並容許旁邊有其餘元素。 |
可否設置width和height | 能 | 能 | 不能 設置會被忽略 |
可使用vertical-align對齊 | 不能夠 | 能夠 | 能夠 |
邊距(margin)和填充(padding) | 各個方向都存在 | 各個方向都存在 | 只有水平方向存在。垂直方向會被忽略。 儘管border和padding在content周圍,但垂直方向上的空間取決於'line-height' |
浮動(float) | - | - | 就像一個block元素,能夠設置垂直邊距和填充。 |
水平居中
垂直居中
水平垂直居中
!important > 行內樣式 > #id > .class > tag > * > 繼承 > 默認
選擇器 從右往左 解析
瀏覽器從最右邊的選擇器(關鍵選擇器)開始查找,根據關鍵選擇器,瀏覽器從 DOM 中篩選出元素,而後向上遍歷被選元素的父元素,判斷是否匹配。
例如,對於形如p span的選擇器,瀏覽器首先找到全部<span>元素,並遍歷它的父元素直到根元素以找到<p>元素。對於特定的<span>,只要找到一個<p>,就知道已經匹配並中止繼續匹配。
基於以上原理,爲了編寫高效CSS,應注意如下幾點:
優勢:
缺點:
區別:
CSS能夠拆分紅2部分:公共CSS 和 業務CSS:
響應式設計就是網站可以兼容多個終端,而不是爲每一個終端作一個特定的版本
基本原理是利用CSS3媒體查詢,爲不一樣尺寸的設備適配不一樣樣式
對於低版本的IE,可採用JS獲取屏幕寬度,而後經過resize方法來實現兼容
$(window).resize(function () {
screenRespond();
});
screenRespond();
function screenRespond(){
var screenWidth = $(window).width();
if(screenWidth <= 1800){
$("body").attr("class", "w1800");
}
if(screenWidth <= 1400){
$("body").attr("class", "w1400");
}
if(screenWidth > 1800){
$("body").attr("class", "");
}
}
複製代碼
// 把上、左、右三條邊隱藏掉(顏色設爲 transparent)
#demo {
width: 0;
height: 0;
border-width: 20px;
border-style: solid;
border-color: transparent transparent red transparent;
}
複製代碼
當使用translate()時,元素仍然佔據其原始空間(有點像position:relative),這與改變絕對定位不一樣。
一本爲新一代CSS所寫的新一代CSS圖書。在我所知的技術專家中,沒人比Lea Verou更能領會新一代CSS的精髓。 ——Jeffrey Zeldman, 《網站重構》做者