語義化讓網頁結構更加清晰,便於瀏覽器、搜索引擎的解析,便於閱讀維護。javascript
語義化標籤php
加強表單css
新增的表單屬性html
視頻和音頻前端
canvas/svg繪圖vue
地理位置html5
拖放Apijava
Web Workernode
Web Storagereact
webSocket
標準模式
和怪異模式
,data-
出現。dataset
getAttribute
setAttribute
data()
canavs
是h5新增一種用戶繪製圖形的容器標籤,經過js繪製,經常使用於動畫,遊戲頁面,數據可視化。
position: absolute;/*絕對定位*/
position: relative; /*相對定位*/
position: flexd; /*固定定位* / 複製代碼
指瀏覽器不用等待全部頁面資源都渲染好以後再呈現給用戶看,而是邊下載邊渲染,因此用戶打開一個網頁的時候每每不能第一時間看到全部的內容,可是可以看到一個大概的樣子,後續的內容瀏覽器會慢慢補上造成一個完整的頁面。
是一種將業務邏輯層和表現層分離,將規定格式的模板代碼轉化爲業務數據的實現
區別
優雅降級從複雜開始,漸進加強則從一個基礎的版本開始,並不斷擴充。
Link 屬於 html 標籤,而@import 是 CSS 中提供的
在頁面加載的時候,link會同時被加載,而@import引用的CSS會在頁面加載完成後纔會加載引用的CSS
@import只有在ie5以上才能夠被識別,而link是html標籤,不存在瀏覽器兼容性問題
link引入樣式的權重大於@import的引用(@import 是將引用的樣式導入到當前的頁面中)
clear:both
;在浮動的盒子下面再放一個標籤,使用 clear:both;來清除浮動
使用 overflow
清除浮動, 找到浮動盒子的父元素,給父元素添加overflow:hidden;
屬性
.clearfix:after {
content:"";
height:0;
line-height:0;
display:block;
clear:both;
visibility:hidden;
}
// 兼容IE6
.clearfix {
zoom: 1;
}
複製代碼
1.id選擇器( # myid)
2.類選擇器(.myclassname)
3.標籤選擇器(div, h1, p)
4.相鄰選擇器(h1 + p)
5.子選擇器(ul < li)
6.後代選擇器(li a)
7.通配符選擇器( * )
8.屬性選擇器(a[rel = "external"])
9.僞類選擇器(a: hover, li: nth-child)
* 可繼承: font-size font-family color, UL LI DL DD DT;
* 不可繼承 :border padding margin width height ;
* 優先級就近原則,樣式定義最近者爲準;
* 載入樣式以最後載入的定位爲準;
優先級爲:
!important > id > class > tag important 比 內聯優先級高
CSS3新增僞類舉例:
p:first-of-type 選擇屬於其父元素的首個 <p> 元素的每一個 <p> 元素。
p:last-of-type 選擇屬於其父元素的最後 <p> 元素的每一個 <p> 元素。
p:only-of-type 選擇屬於其父元素惟一的 <p> 元素的每一個 <p> 元素。
p:only-child 選擇屬於其父元素的惟一子元素的每一個 <p> 元素。
p:nth-child(2) 選擇屬於其父元素的第二個子元素的每一個 <p> 元素。
:enabled、:disabled 控制表單控件的禁用狀態。
:checked,單選框或複選框被選中。
複製代碼
塊級元素(block)特性:
內聯元素(inline)特性:
<input> 、<img> 、<button> 、<texterea> 、<label>。
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
position: absolute; /*父元素須要相對定位*/
top: 50%;
left: 50%;
margin-top: -100px; /*設爲高度的1/2*/
margin-left: -100px; /*設爲寬度的1/2*/
}
複製代碼
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
position: absolute; /*父元素須要相對定位*/
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /*在水平和垂直方向上各偏移-50%*/
}
複製代碼
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
margin: auto; /*很關鍵的一步*/
position: absolute; /*父元素須要相對定位*/
left: 0;
top: 0;
right: 0;
bottom: 0; /*讓四個定位屬性都爲0*/
}
複製代碼
body {
display: flex; /*設置外層盒子display爲flex*/
align-items: center; /*設置內層盒子的垂直居中*/
justify-content: center; /*設置內層盒子的水平居中*/
.content {
width: 200px;
height: 200px;
background-color: #6699ff;
}
}
複製代碼
.content {
/* img的容器設置以下 */
display: table-cell;
text-align: center;
vertical-align: middle;
}
複製代碼
什麼是 BFC
BFC(Block Formatting Context)格式化上下文,是 Web 頁面中盒模型佈局的 CSS 渲染模式,指一個獨立的渲染區域或者說是一個隔離的獨立容器。
造成 BFC 的條件
BFC 的特性
span {
width: 0;
heigh: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid #ff0000;
}
複製代碼
他們是CSS預處理器。是 CSS 上的一種抽象層。他們是一種特殊的語法/語言編譯成 CSS。
爲何要使用它們?
概念:
將多個小圖片拼接到一個圖片中。經過 background-position 和元素尺寸調節須要顯示的背景圖案。
優勢:
缺點:
IOS8+下已經支持帶小數的px值,media query 對應 devicePixelRatio 有個查詢值 -webkit-min-device-pixel-ratio;
.border { border: 1px solid #999 }
@media screen and (-webkit-min-device-pixel-ratio: 2) {
.border { border: 0.5px solid #999 }
}
@media screen and (-webkit-min-device-pixel-ratio: 3) {
.border { border: 0.333333px solid #999 }
}
複製代碼
<body><div id="main" style="border: 1px solid #000000;"></div></body>
<script type="text/javascript"> if (window.devicePixelRatio && devicePixelRatio >= 2) { var main = document.getElementById('main'); main.style.border = '.5px solid #000000'; } </script>
複製代碼
<meta name="viewport" id="WebViewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
複製代碼
*var* viewport = document.querySelector("meta[name=viewport]")
if (window.devicePixelRatio == 1) {
viewport.setAttribute('content', 'width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no')
}
if (window.devicePixelRatio == 2) {
viewport.setAttribute('content', 'width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no')
}
if (window.devicePixelRatio == 3) {
viewport.setAttribute('content', 'width=device-width, initial-scale=0.333333333, maximum-scale=0.333333333, minimum-scale=0.333333333, user-scalable=no')
}
*var* docEl = document.documentElement;
*var* fontsize = 10 * (docEl.clientWidth / 320) + 'px';
docEl.style.fontSize = fontsize;
複製代碼
div {
-webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.5);
}
複製代碼
/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
.border-bottom::after {
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
.border-bottom::after {
-webkit-transform: scaleY(0.33);
transform: scaleY(0.33);
}
}
複製代碼
div {
height:1px;
background:#000;
-webkit-transform: scaleY(0.5);
-webkit-transform-origin:0 0;
overflow: hidden;
}
複製代碼
單列布局
兩列自適應佈局
聖飛佈局和雙飛翼佈局
flxd佈局
彈性盒子是 CSS3 的一種新的佈局模式。
CSS3 彈性盒( Flexible Box 或 flexbox),是一種當頁面須要適應不一樣的屏幕大小以及設備類型時確保元素擁有恰當的行爲的佈局方式。
引入彈性盒佈局模型的目的是提供一種更加有效的方式來對一個容器中的子元素進行排列、對齊和分配空白空間。
base64 是網絡上最多見的用於傳輸 8Bit 字節代碼的編碼方式之一,要求把每三個 8Bit 的字節轉換爲四個 6Bit 的字節,Base64 是網絡上最多見的用於傳輸 8Bit 字節代碼的編碼方式之一。
通俗點講:將資源本來二進制形式轉成以 64 個字符基本單位,所組成的一串字符串。
好比一張圖片轉成 base64 編碼後就像這樣,圖片直接以 base64 形式嵌入文件中(很長沒截完):
- 生成 base64 編碼:
圖片生成 base64 能夠用一些工具,如在線工具,但在項目中這樣一個圖片這樣生成是挺繁瑣。
特別說下,webpack 中的 url-loader 能夠完成這個工做,能夠對限制大小的圖片進行 base64 的轉換,很是方便。
- 優勢:
base64 的圖片會隨着 html 或者 css 一塊兒下載到瀏覽器,減小了請求.
可避免跨域問題
- 缺點:
老東西(低版本)的 IE 瀏覽器不兼容。
體積會比原來的圖片大一點。
css 中過多使用 base64 圖片會使得 css 過大,不利於 css 的加載。
- 適用場景:
應用於小的圖片幾 k 的,太大的圖片會轉換後的大小太大,得不償失。
用於一些 css sprites 不利處理的小圖片,如一些能夠經過 background-repeat 平鋪來作成背景的圖片
複製代碼
偏移
offsetWidth width + padding + border
offsetHeight height + padding + border
offsetLeft
offsetTop
offsetParent
注意:沒有offsetRight和offsetBottom
************************************************************************************************
捲曲
scrollWidth width + padding
scrollHeight 當內部的內容溢出盒子的時候, 頂邊框的底部,計算到內容的底部;若是內容沒有溢出盒子,計算方式爲盒子內部的真實高度(邊框到邊框)
scrollLeft 這個scroll系列屬性不是隻讀的
scrollTop
scroll()
此函數能夠獲取捲曲的高度和捲曲的寬度
function myScroll() {
return {
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0
};
}
滾動滾動條的時候觸發事件
box(window).onscroll = function () {}
************************************************************************************************
可視
clientWidth 獲取的是元素內部的真實寬度 width + padding
clientHeight 邊框之間的高度
clientLeft 至關於左邊框的寬度 若是元素包含了滾動條,而且滾動條顯示在元素的左側。這時,clientLeft屬性會包含滾動條的寬度17px
clientTop 至關於頂邊框的寬度
client()
此函數能夠獲取瀏覽器可視區域的寬高
function myClient() {
return {
wid: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0,
heit: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0
};
}
\----------------------------------------------------------------------------------------------
@offsetHeight和style.height的區別
demo.style.height只能獲取行內樣式,若是樣式寫到了其餘地方,甚至根本就沒寫,便沒法獲取
style.height是字符串(並且帶單位),offsetHeight是數值
demo.style.height能夠設置行內樣式,offsetHeight是隻讀屬性
所以,通常用demo.offsetHeight來獲取某元素的真實寬度/高度,用style.height來設置寬度/高度
\----------------------------------------------------------------------------------------------
@offsetLeft和style.left的區別
1、style.left只能獲取行內樣式
2、offsetLeft只讀,style.left可讀可寫
3、offsetLeft是數值,style.left是字符串而且有單位px
4、若是沒有加定位,style.left獲取的數值多是無效的
5、最大區別在於offsetLeft以border左上角爲基準,style.left以margin左上角爲基準
\----------------------------------------------------------------------------------------------
@scrollHeight和scrollWidth
標籤內部實際內容的高度/寬度
不計算邊框,若是內容不超出盒子,值爲盒子的寬高(不帶邊框)
若是內容超出了盒子,就是從頂部或左部邊框內側一直到內容a的最外部分
\----------------------------------------------------------------------------------------------
@scrollTop和scrollLeft
被捲去部分的 頂部/左側 到可視區域 頂部/左側 的距離
複製代碼
在肯定問題緣由和有問題的瀏覽器後,使用單獨的樣式表,僅供出現問題的瀏覽器加載。這種方法須要使用服務器端渲染。
使用已經處理好此類問題的庫,好比 Bootstrap。
使用 autoprefixer
自動生成 CSS 屬性前綴。
使用 Reset CSS 或 Normalize.css。
優雅的降級:爲現代瀏覽器構建應用,同時確保它在舊版瀏覽器中正常運行。
漸進式加強:構建基於用戶體驗的應用,但在瀏覽器支持時添加新增功能。
利用 caniuse.com 檢查特性支持。
使用 autoprefixer
自動生成 CSS 屬性前綴。
使用 Modernizr進行特性檢測。
{box-sizing: border-box;}
會產生怎樣的效果?元素默認應用了box-sizing: content-box
,元素的寬高只會決定內容(content)的大小。
box-sizing: border-box
改變計算元素width
和height
的方式,border
和padding
的大小也將計算在內。
元素的height
= 內容(content)的高度 + 垂直方向的padding
+ 垂直方向border
的寬度
元素的width
= 內容(content)的寬度 + 水平方向的padding
+ 水平方向border
的寬度
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
複製代碼
display: -webkit-box;
-webkit-box-orient: vertical;
/* 最多顯示幾行*/
-webkit-line-clamp: 3;
overflow: hidden;
複製代碼
function Person(name) {
var o = new Object;
o.age = name;
o.sayName = function(){
console.log(this.name);
}
return o;
}
// 缺點:對象沒法識別
複製代碼
function person(name) {
this.name = name;
// 優化點:能夠把函數放到外面,這樣每次建立實例的時候函數就不會被從新建立
this.sayName = function() {
console.log(this.name)
}
}
// 優勢:能夠識別對象的類型
// 缺點:每次建立實例函數都要從新建立一遍
複製代碼
function Person() {}
person.prototype.name = 'nick';
person.prototype.sayName = function(){
console.log(this.name);
}
var person1 = new Person();
// 優勢:方法和屬性都共享
// 缺點:不能初始化參數
// 優化版
function Person(name) {}
Person.prototype = {
constructor: Person,
name: 'nick',
getName: function () {
console.log(this.name);
}
};
var person1 = new Person();
// 能夠經過constructor找到所屬構造函數
複製代碼
function Person(name) {
this.name = name;
}
person.prototype = function() {
console.log(this.name);
}
const person = new Person('nick');
// 優勢:方法共享,變量私有。
複製代碼
function Person(name) {
this.name = name;
if (typeof this.sayName != 'function') {
Person.prototype.sayName = function() {
console.log(this.name);
}
}
}
複製代碼
function Person(name) {
var o = new Object;
o.age = name;
o.sayName = function(){
console.log(this.name);
}
return o;
}
// 示例
function SpecialArray() {
var values = new Array();
for (var i = 0, len = arguments.length; i < len; i++) {
values.push(arguments[i]);
}
values.toPipedString = function () {
return this.join("|");
};
return values;
}
var colors = new SpecialArray('red', 'blue', 'green');
var colors2 = SpecialArray('red2', 'blue2', 'green2');
console.log(colors);
console.log(colors.toPipedString()); // red|blue|green
console.log(colors2);
console.log(colors2.toPipedString()); // red2|blue2|green2
// 你會發現,其實所謂的寄生構造函數模式就是比工廠模式在建立對象的時候,多使用了一個new,實際上二者的結果是同樣的。
複製代碼
function Person(name) {
var o = new Object;
o.sayName = function(){
console.log(this.name);
}
return o;
}
// 沒有公共屬性
複製代碼
__proto__
屬性指向構造函數的原型對象。(原型.prototype)// 定義構造函數
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1.make);
// expected output: "Eagle"
複製代碼
變量必須先聲明,再使用
不能對變量執行delete操做
對象的屬性名不能重複
禁用eval()
函數的arguments參數
禁用with(){}
複製代碼
全局做用域
:在代碼中任何地方都能訪問到的對象擁有全局做用域。
window對象的屬性
定義在最外層的函數或變量
未定義直接賦值的變量
局部做用域
:通常在代碼片斷內能夠訪問到的,最多見的如函數內部,因此又稱函數做用域
塊級做用域
: 在任何一對{}
中的定義的變量在代碼塊外都不可見。const ary = [1,2,3,4,5,6];
Math.max(1,2,3,4,5,6);
Math.max.call()
1 === '1'
1== '1'
[1] == [2]
複製代碼
script
標籤沒有跨域限制的漏洞,從其餘來源動態獲取數據,jsonp請求須要服務器支持才能夠,jsonp屬於非同源get
請求,但可能會遭受xss
攻擊W3C
標準,全稱是跨域資源共享
,容許瀏覽器向跨域服務器發送XMLHttpRequest
/Fetch
請求。res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("Content-Type", "application/json;charset=utf-8");
複製代碼
Websocket
是一種雙向通訊協議,創建鏈接以後,server
端和client
端都能主動向對方接收/發送數據。瞭解過,沒用過。
淺拷貝
Object.assign()
:將全部可枚舉的值從一個或多個源對象複製到目標對象Array.prototype.slice()
返回數組的淺拷貝深拷貝
JSON.parse(JSON.stringify(object))
進行深拷貝,但會有幾個問題,好比不能處理正則,不能處理new Date
,不能序列化函數,會忽略undefined
和symbol
總結:
實現一個深拷貝
// 簡單深拷貝
const cloneDeep = (source) => {
let target = Array.isArray(source) ? [] : {};
for(const key in source) {
const val = source[key];
if(typeof val === 'object') {
target[key] = cloneDeep(val);
} else {
target[key] = val;
}
}
return target;
}
// 加強版的深拷貝
const isObject = (object) => {
// 兼容數組
return typeof object === 'object' && object != null;
}
const cloneDeep = (source) => {
// 參數校驗
if(!isObject(source)) return source;
let target = Array.isArray(source) ? [] : {};
// 哈希表解決循環引用
let hash = new WeakMap();
hash.set(source, target);
for (const key in source) {
// hasOwnProperty: 檢測對象自身屬性中是否具備指定的屬性,返回布爾值
if (source.hasOwnProperty(key)) {
if(typeof source[key] === 'object') {
// 遞歸實現深拷貝
target[key] = cloneDeep(source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
}
var a = {
name: "muyiy",
book: {
title: "You Don't Know JS",
price: "45",
demo: {
demo: {
demo: {}
},
demo1: {
demo: {}
},
demo2: {
demo: {}
}
}
},
a1: undefined,
a2: null,
a3: 123
}
var b = cloneDeep(a);
a.name = "高級前端進階";
a.book.price = "55";
a.circleRef = a;
b.book.demo.demo.demo.a = 2;
console.log(a);
console.log(b);
複製代碼
原型
prototype
屬性,這是屬性是指向構造函數
的原型對象
,這個對象包含全部實例共享的屬性和方法。constructor
屬性,這個屬性指向所關聯的構造函數。__proto__
屬性[非標準的方法],這個屬性指向構造函數的原型prototype
原型鏈
__proto__
屬性去原型上查找,若是尚未找到則會在構造函數的原型的__proto__
中查找,這樣一層層向上查找就會造成一個做用域鏈,稱爲原型鏈
爲何要有原型鏈
手繪原型圖

event.stopPropagation()
//非標準,已廢棄
event.cancelBubble=false; // IE
複製代碼
event.preventDefault()
//非標準,已廢棄
event.returnValue=false; //IE
複製代碼
let getJson = url => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return;
if (xhr.readyState === 4 && 200 === xhr.status) {
resolve(xhr.responseText);
} else {
reject();
}
};
xhr.send();
});
};
getJson('/login').then(function (res) {
return getJson('/order');
}).then(function(res){
console.log(res);
}).catch(function (err) {
console.log('error')
})
複製代碼
let xhr = new XMLHttpRequest();
xhr.open('get', 'http://xxx.com');
xhr.onreadystatechange = () => {
if (xhr.readyState !== 4) return;
if (200 === xhr.status) {
console.log(xhr.responseText)
}
};
xhr.send();
複製代碼
指的是某個函數在某段時間內,不管觸發了多少次回調,都只執行最後一次。
實現方案 使用定時器,函數第一次執行時設定一個定時器,以後調用時發現已經設定過定時器就清空以前的定時器,並從新設定一個新的定時器,若是存在沒有被清空的定時器,當定時器計時結束後觸發函數執行
示例
/** * 延遲執行 * fn: 須要防抖的函數 * wait: 時間間隔 * */
function debounce(fn, wait = 50) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, wait)
}
}
/** * 當即執行 * fn: 須要防抖的函數 * wait: 時間間隔 * */
function debounce(fn, wait = 50) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
let callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait);
if (callNow) fn.apply(this, args);
}
}
複製代碼
函數節流指的是某個函數在必定時間間隔內只執行一次,在這間隔內無視後來產生的函數調用請求
實現方案
每次執行時設定一個上次執行的時間戳,判斷是否已到執行時間,若是到了就執行。
設定一個定時器,若是定時器存在則直接返回,等待異步執行完畢清空定時器。
示例
// 時間戳
const throttle = (fn, wait = 50) => {
// 上一次執行 fn 的時間
let previous = 0;
// 將 throttle 處理結果看成函數返回
return function(...args) {
// 獲取當前時間,轉換成時間戳,單位毫秒
let now = +new Date();
// 將當前時間和上一次執行函數的時間進行對比
// 大於等待時間就把 previous 設置爲當前時間並執行函數 fn
if (now - previous > wait) {
previous = now
fn.apply(this, args)
}
}
}
// 定時器版本
const throttle = function(fn, wait) {
let timer = null;
return function(...args) {
if (timer) return;
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, wait);
};
}
複製代碼
const ary1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
const ary2 = ary1.filter((element, index, ary) => {
// 判斷索引是否相等
return ary.indexOf(element) === index;
}) // => [1, 2, 3, 5, 4]
const ary3 = [...new Set(arr1)]
// => [1, 2, 3, 5, 4]
const ary4 = Array.from(new Set(arr1))
// => [1, 2, 3, 5, 4]
const ary5 = arr1.reduce((prev, next) => {
return prev.includes(next) ? prev : [...prev, next];
}, []);
複製代碼
_proto_
屬性指向構造函數的原型對象。(原型.prototype)// 定義構造函數
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
var car1 = new Car('Eagle', 'Talon TSi', 1993);
console.log(car1.make);
// expected output: "Eagle"
複製代碼
call
:使用一個指定的 this 值和單獨給出的一個或多個參數來調用一個函數。fun.call(thisArg[,arg1[,arg2[, ...]]])
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name); //=>"cheese"
複製代碼
apply
: 調用一個具備給定this值的函數,以及做爲一個數組(或相似數組對象)提供的參數fun.apply(thisArg, argsArray)
var numbers = [5, 6, 2, 3, 7];
// 最大值
var max = Math.max.apply(null, numbers);
console.log(max); //=> 7
// 最小值
var min = Math.min.apply(null, numbers);
console.log(min); //=> 2
複製代碼
bind
:建立一個新的函數,在bind
被調用時,這個新函數的this被bind的第一個參數指定,其他的參數將做爲新函數的參數供調用時使用。function.bind(thisArg[,arg1[,arg2[, ...]]])
var module = {
x: 42,
getX: function() {
return this.x;
}
}
var unboundGetX = module.getX;
console.log(unboundGetX()); // => undefined
var boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // => 42
複製代碼
console.log(Array.from('foo'));
// expected output: Array ["f", "o", "o"]
console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]
複製代碼
Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false
複製代碼
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
console.log(array1.concat(array2));
// expected output: Array ["a", "b", "c", "d", "e", "f"]
複製代碼
var array1 = [1, 30, 39, 29, 10, 13];
function isBelowThreshold(currentValue) {
return currentValue < 40;
}
console.log(array1.every(isBelowThreshold));
// expected output: true
複製代碼
var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
複製代碼
var array = [1, 2, 3, 4, 5];
var even = function(element) {
// checks whether an element is even
return element % 2 === 0;
};
console.log(array.some(even));
// expected output: true
複製代碼
undefined
。var array1 = [5, 12, 8, 130, 44];
var found = array1.find(function(element) {
return element > 10;
});
console.log(found);
// expected output: 12
複製代碼
var array1 = [5, 12, 8, 130, 44];
function isLargeNumber(element) {
return element > 13;
}
console.log(array1.findIndex(isLargeNumber));
// expected output: 3
複製代碼
var array1 = ['a', 'b', 'c'];
array1.forEach(function(element) {
console.log(element);
});
// expected output: "a"
// expected output: "b"
// expected output: "c"
複製代碼
var array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
複製代碼
var array1 = [1, 2, 3];
console.log(array1.includes(2));
// expected output: true
var pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));
// expected output: true
console.log(pets.includes('at'));
// expected output: false
複製代碼
var beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];
console.log(beasts.indexOf('bison'));
// expected output: 1
// start from index 2
console.log(beasts.indexOf('bison', 2));
// expected output: 4
console.log(beasts.indexOf('giraffe'));
// expected output: -1
複製代碼
var animals = ['Dodo', 'Tiger', 'Penguin', 'Dodo'];
console.log(animals.lastIndexOf('Dodo'));
// expected output: 3
console.log(animals.lastIndexOf('Tiger'));
// expected output: 1
複製代碼
var elements = ['Fire', 'Air', 'Water'];
console.log(elements.join());
// expected output: "Fire,Air,Water"
console.log(elements.join(''));
// expected output: "FireAirWater"
console.log(elements.join('-'));
// expected output: "Fire-Air-Water"
複製代碼
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity 做爲深度,展開任意深度的嵌套數組
arr3.flat(Infinity);
// [1, 2, 3, 4, 5, 6]
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
複製代碼
var arr1 = [1, 2, 3, 4];
arr1.map(x => [x * 2]);
// [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]
// 只會將 flatMap 中的函數返回的數組 「壓平」 一層
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]
let arr = ["今每天氣不錯", "", "早上好"]
arr.map(s => s.split(""))
// [["今", "天", "天", "氣", "不", "錯"],[],["早", "上", "好"]]
arr.flatMap(s => s.split(''));
// ["今", "天", "天", "氣", "不", "錯", "早", "上", "好"]
複製代碼
var array1 = ['a', 'b', 'c'];
var iterator = array1.keys();
for (let key of iterator) {
console.log(key); // expected output: 0 1 2
}
複製代碼
const array1 = ['a', 'b', 'c'];
const iterator = array1.values();
for (const value of iterator) {
console.log(value); // expected output: "a" "b" "c"
}
複製代碼
var plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];
console.log(plants.pop());
// expected output: "tomato"
console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage", "kale"]
plants.pop();
console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage"]
複製代碼
const animals = ['pigs', 'goats', 'sheep'];
const count = animals.push('cows');
console.log(count);
// expected output: 4
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows"]
animals.push('chickens', 'cats', 'dogs');
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]
複製代碼
var array1 = [1, 2, 3];
var firstElement = array1.shift();
console.log(array1);
// expected output: Array [2, 3]
console.log(firstElement);
// expected output: 1
複製代碼
var array1 = [1, 2, 3];
console.log(array1.unshift(4, 5));
// expected output: 5
console.log(array1);
// expected output: Array [4, 5, 1, 2, 3]
複製代碼
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
複製代碼
const array1 = [[0, 1], [2, 3], [4, 5]].reduceRight(
(accumulator, currentValue) => accumulator.concat(currentValue)
);
console.log(array1);
// expected output: Array [4, 5, 2, 3, 0, 1]
複製代碼
var array1 = ['one', 'two', 'three'];
console.log('array1: ', array1);
// expected output: Array ['one', 'two', 'three']
var reversed = array1.reverse();
console.log('reversed: ', reversed);
// expected output: Array ['three', 'two', 'one']
/* Careful: reverse is destructive. It also changes the original array */
console.log('array1: ', array1);
// expected output: Array ['three', 'two', 'one']
複製代碼
var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]
console.log(animals.slice(2, 4));
// expected output: Array ["camel", "duck"]
console.log(animals.slice(1, 5));
// expected output: Array ["bison", "camel", "duck", "elephant"]
複製代碼
var months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at index 1
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'June']
months.splice(4, 1, 'May');
// replaces 1 element at index 4
console.log(months);
// expected output: Array ['Jan', 'Feb', 'March', 'April', 'May']
複製代碼
var months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
var array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
複製代碼
var array1 = [1, 'a', new Date('21 Dec 1997 14:12:00 UTC')];
var localeString = array1.toLocaleString('en', {timeZone: "UTC"});
console.log(localeString);
// expected output: "1,a,12/21/1997, 2:12:00 PM",
// This assumes "en" locale and UTC timezone - your results may vary
複製代碼
var array1 = [1, 2, 'a', '1a'];
console.log(array1.toString());
// expected output: "1,2,a,1a"
複製代碼
console.log(String.fromCharCode(189, 43, 190, 61));
// expected output: "½+¾="
複製代碼
console.log(String.fromCodePoint(9731, 9733, 9842, 0x2F804));
// expected output: "☃★♲你"
複製代碼
var anyString = "Brave new world";
console.log("The character at index 0 is '" + anyString.charAt(0) + "'");
console.log("The character at index 1 is '" + anyString.charAt(1) + "'");
console.log("The character at index 2 is '" + anyString.charAt(2) + "'");
console.log("The character at index 3 is '" + anyString.charAt(3) + "'");
console.log("The character at index 4 is '" + anyString.charAt(4) + "'");
console.log("The character at index 999 is '" + anyString.charAt(999) + "'");
複製代碼
var sentence = 'The quick brown fox jumps over the lazy dog.';
var index = 4;
console.log('The character code ' + sentence.charCodeAt(index) + ' is equal to ' + sentence.charAt(index));
// expected output: "The character code 113 is equal to q"
複製代碼
'ABC'.codePointAt(1); // 66
'\uD800\uDC00'.codePointAt(0); // 65536
'XYZ'.codePointAt(42); // undefined
複製代碼
var hello = "Hello, ";
console.log(hello.concat("Kevin", " have a nice day.")); /* Hello, Kevin have a nice day. */
複製代碼
const str1 = 'Saturday night plans';
console.log(str1.startsWith('Sat'));
// expected output: true
console.log(str1.startsWith('Sat', 3));
// expected output: false
複製代碼
const str1 = 'Cats are the best!';
console.log(str1.endsWith('best', 17));
// expected output: true
const str2 = 'Is this a question';
console.log(str2.endsWith('?'));
// expected output: false
複製代碼
var str = 'To be, or not to be, that is the question.';
console.log(str.includes('To be')); // true
console.log(str.includes('question')); // true
console.log(str.includes('nonexistent')); // false
console.log(str.includes('To be', 1)); // false
console.log(str.includes('TO BE')); // false
複製代碼
var paragraph = 'The quick brown fox jumps over the lazy dog. If the dog barked, was it really lazy?';
var searchTerm = 'dog';
var indexOfFirst = paragraph.indexOf(searchTerm);
console.log('The index of the first "' + searchTerm + '" from the beginning is ' + indexOfFirst);
// expected output: "The index of the first "dog" from the beginning is 40"
console.log('The index of the 2nd "' + searchTerm + '" is ' + paragraph.indexOf(searchTerm, (indexOfFirst + 1)));
// expected output: "The index of the 2nd "dog" is 52"
複製代碼
"canal".lastIndexOf("a") // returns 3
"canal".lastIndexOf("a",2) // returns 1
"canal".lastIndexOf("a",0) // returns -1
"canal".lastIndexOf("x") // returns -1
// 區分大小寫
"Blue Whale, Killer Whale".lastIndexOf("blue"); // returns -1
複製代碼
// The letter "a" is before "c" yielding a negative value
'a'.localeCompare('c');
// -2 or -1 (or some other negative value)
// Alphabetically the word "check" comes after "against" yielding a positive value
'check'.localeCompare('against');
// 2 or 1 (or some other positive value)
// "a" and "a" are equivalent yielding a neutral value of zero
'a'.localeCompare('a');
// 0
複製代碼
var str = 'For more information, see Chapter 3.4.5.1';
var re = /see (chapter \d+(\.\d)*)/i;
var found = str.match(re);
console.log(found);
// logs [ 'see Chapter 3.4.5.1',
// 'Chapter 3.4.5.1',
// '.1',
// index: 22,
// input: 'For more information, see Chapter 3.4.5.1' ]
// 'see Chapter 3.4.5.1' 是整個匹配。
// 'Chapter 3.4.5.1' 被'(chapter \d+(\.\d)*)'捕獲。
// '.1' 是被'(\.\d)'捕獲的最後一個值。
// 'index' 屬性(22) 是整個匹配從零開始的索引。
// 'input' 屬性是被解析的原始字符串。
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);
console.log(matches_array);
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
複製代碼
const regexp = RegExp('foo*','g');
const str = 'table football, foosball';
while ((matches = regexp.exec(str)) !== null) {
console.log(`Found ${matches[0]}. Next starts at ${regexp.lastIndex}.`);
// expected output: "Found foo. Next starts at 9."
// expected output: "Found foo. Next starts at 19."
}
//===
const regexp = RegExp('foo*','g');
const str = 'table football, foosball';
let matches = str.matchAll(regexp);
for (const match of matches) {
console.log(match);
}
// Array [ "foo" ]
// Array [ "foo" ]
// matches iterator is exhausted after the for..of iteration
// Call matchAll again to create a new iterator
matches = str.matchAll(regexp);
Array.from(matches, m => m[0]);
// Array [ "foo", "foo" ]
複製代碼
// Initial string
// U+1E9B: LATIN SMALL LETTER LONG S WITH DOT ABOVE
// U+0323: COMBINING DOT BELOW
var str = "\u1E9B\u0323";
// Canonically-composed form (NFC)
// U+1E9B: LATIN SMALL LETTER LONG S WITH DOT ABOVE
// U+0323: COMBINING DOT BELOW
str.normalize("NFC"); // "\u1E9B\u0323"
str.normalize(); // same as above
// Canonically-decomposed form (NFD)
// U+017F: LATIN SMALL LETTER LONG S
// U+0323: COMBINING DOT BELOW
// U+0307: COMBINING DOT ABOVE
str.normalize("NFD"); // "\u017F\u0323\u0307"
// Compatibly-composed (NFKC)
// U+1E69: LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
str.normalize("NFKC"); // "\u1E69"
// Compatibly-decomposed (NFKD)
// U+0073: LATIN SMALL LETTER S
// U+0323: COMBINING DOT BELOW
// U+0307: COMBINING DOT ABOVE
str.normalize("NFKD"); // "\u0073\u0323\u0307"
複製代碼
'abc'.padEnd(10); // "abc "
'abc'.padEnd(10, "foo"); // "abcfoofoof"
'abc'.padEnd(6, "123456"); // "abc123"
'abc'.padEnd(1); // "abc"
複製代碼
'abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
'abc'.padStart(8, "0"); // "00000abc"
'abc'.padStart(1); // "abc"
複製代碼
"abc".repeat(-1) // RangeError: repeat count must be positive and less than inifinity
"abc".repeat(0) // ""
"abc".repeat(1) // "abc"
"abc".repeat(2) // "abcabc"
"abc".repeat(3.5) // "abcabcabc" 參數count將會被自動轉換成整數.
"abc".repeat(1/0) // RangeError: repeat count must be positive and less than inifinity
({toString : () => "abc", repeat : String.prototype.repeat}).repeat(2)
//"abcabc",repeat是一個通用方法,也就是它的調用者能夠不是一個字符串對象.
複製代碼
var p = 'The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?';
var regex = /dog/gi;
console.log(p.replace(regex, 'ferret'));
// expected output: "The quick brown fox jumps over the lazy ferret. If the ferret reacted, was it really lazy?"
console.log(p.replace('dog', 'monkey'));
// expected output: "The quick brown fox jumps over the lazy monkey. If the dog reacted, was it really lazy?"
複製代碼
var paragraph = 'The quick brown fox jumps over the lazy dog. If the dog barked, was it really lazy?';
// any character that is not a word character or whitespace
var regex = /[^\w\s]/g;
console.log(paragraph.search(regex));
// expected output: 43
console.log(paragraph[paragraph.search(regex)]);
// expected output: "."
複製代碼
var str = 'The quick brown fox jumps over the lazy dog.';
console.log(str.slice(31));
// expected output: "the lazy dog."
console.log(str.slice(4, 19));
// expected output: "quick brown fox"
console.log(str.slice(-4));
// expected output: "dog."
console.log(str.slice(-9, -5));
// expected output: "lazy"
複製代碼
var str = 'The quick brown fox jumps over the lazy dog.';
var words = str.split(' ');
console.log(words[3]);
// expected output: "fox"
var chars = str.split('');
console.log(chars[8]);
// expected output: "k"
var strCopy = str.split();
console.log(strCopy);
// expected output: Array ["The quick brown fox jumps over the lazy dog."]
複製代碼
var anyString = "Mozilla";
// 輸出 "Moz"
console.log(anyString.substring(0,3));
console.log(anyString.substring(3,0));
console.log(anyString.substring(3,-3));
console.log(anyString.substring(3,NaN));
console.log(anyString.substring(-2,3));
console.log(anyString.substring(NaN,3));
// 輸出 "lla"
console.log(anyString.substring(4,7));
console.log(anyString.substring(7,4));
// 輸出 ""
console.log(anyString.substring(4,4));
// 輸出 "Mozill"
console.log(anyString.substring(0,6));
// 輸出 "Mozilla"
console.log(anyString.substring(0,7));
console.log(anyString.substring(0,10));
複製代碼
console.log('ALPHABET'.toLocaleLowerCase());
// 'alphabet'
console.log('中文簡體 zh-CN || zh-Hans'.toLocaleLowerCase());
// '中文簡體 zh-cn || zh-hans'
複製代碼
console.log('alphabet'.toLocaleUpperCase()); // 'ALPHABET'
複製代碼
console.log('中文簡體 zh-CN || zh-Hans'.toLowerCase());
// 中文簡體 zh-cn || zh-hans
console.log( "ALPHABET".toLowerCase() );
// "alphabet"
複製代碼
console.log( "alphabet".toUpperCase() ); // "ALPHABET"
複製代碼
var x = new String("Hello world");
alert(x.toString()) // 輸出 "Hello world"
複製代碼
var orig = ' foo ';
console.log(orig.trim()); // 'foo'
// 另外一個.trim()例子,只從一邊刪除
var orig = 'foo ';
console.log(orig.trim()); // 'foo'
複製代碼
var greeting = ' Hello world! ';
console.log(greeting);
// expected output: " Hello world! ";
console.log(greeting.trimEnd());
console.log(greeting.trimRight());
// expected output: " Hello world!";
複製代碼
var str = " foo ";
alert(str.length); // 8
str = str.trimLeft();
alert(str.length); // 5
document.write( str );
複製代碼
x = new String("Hello world");
alert(x.valueOf()) // Displays "Hello world"
複製代碼
String.raw`Hi\n${2+3}!`;
// 'Hi\n5!',Hi 後面的字符不是換行符,\ 和 n 是兩個不一樣的字符
String.raw `Hi\u000A!`;
// "Hi\\u000A!",同上,這裏獲得的會是 \、u、0、0、0、A 6個字符,
// 任何類型的轉義形式都會失效,保留原樣輸出,不信你試試.length
let name = "Bob";
String.raw `Hi\n${name}!`;
// "Hi\nBob!",內插表達式還能夠正常運行
// 正常狀況下,你也許不須要將 String.raw() 看成函數調用。
// 可是爲了模擬 `t${0}e${1}s${2}t` 你能夠這樣作:
String.raw({ raw: 'test' }, 0, 1, 2); // 't0e1s2t'
// 注意這個測試, 傳入一個 string, 和一個相似數組的對象
// 下面這個函數和 `foo${2 + 3}bar${'Java' + 'Script'}baz` 是相等的.
String.raw({
raw: ['foo', 'bar', 'baz']
}, 2 + 3, 'Java' + 'Script'); // 'foo5barJavaScriptbaz'
複製代碼
let
關鍵字,用於聲明只在塊級做用域起做用的變量const
關鍵字,用於聲明常量Symbol
數據類型,定義一個獨一無二的值for...of
遍歷器,可遍歷具備iterator
(迭代器)接口的數據類型Set
結構,用於存儲不重複成員值的集合Map
結構Promise
對象,一種異步操做的解決方案,更合理、規範的操做異步處理。class
類,定義類和更簡便的實現類的繼承var
在任何語句執行前就完成了聲明和初始化funciton
聲明、初始化和賦值在一開始就所有完成,函數變量提高的優先級更高let
先聲明但並無初始化,只有解析到let
那一行纔會進入初始化階段。若是在此做用域前提早訪問,則報錯xx is not defined
, 暫時性死區,在相同做用域內不容許重複聲明同一個變量const
和let
區別在於const
聲明的是一個只讀常亮,一旦聲明後就不能改變一、遍歷器(Iterator)是一種接口,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構只要部署 Iterator 接口,就能夠完成遍歷操做(即依次處理該數據結構的全部成員)
二、Iterator 的做用有三個:
三、默認部署了 Iterator 的數據有 Array、Map、Set、String、TypedArray、arguments、NodeList 對象,ES6 中有的是 Set、Map、
// 一、類的基本定義
class Parent {
constructor(name = "小白") {
this.name = name;
}
}
//=====================================
// 二、生成一個實例
let g_parent = new Parent();
console.log(g_parent); //{name: "小白"}
let v_parent = new Parent("v"); // 'v'就是構造函數name屬性 , 覆蓋構造函數的name屬性值
console.log(v_parent); // {name: "v"}
//=====================================
// 三、繼承
class Parent {
//定義一個類
constructor(name = "小白") {
this.name = name;
}
}
class Child extends Parent {}
console.log("繼承", new Child()); // 繼承 {name: "小白"}
//=====================================
// 四、繼承傳遞參數
class Parent {
//定義一個類
constructor(name = "小白") {
this.name = name;
}
}
class Child extends Parent {
constructor(name = "child") {
// 子類重寫name屬性值
super(name); // 子類向父類修改 super必定放第一行
this.type = "preson";
}
}
console.log("繼承", new Child("hello")); // 帶參數覆蓋默認值 繼承{name: "hello", type: "preson"}
//=====================================
// 五、ES6從新定義的ES5中的訪問器屬性
class Parent {
//定義一個類
constructor(name = "小白") {
this.name = name;
}
get longName() {
// 屬性
return "mk" + this.name;
}
set longName(value) {
this.name = value;
}
}
let v = new Parent();
console.log("getter", v.longName); // getter mk小白
v.longName = "hello";
console.log("setter", v.longName); // setter mkhello
//=====================================
// 六、類的靜態方法
class Parent {
//定義一個類
constructor(name = "小白") {
this.name = name;
}
static tell() {
// 靜態方法:經過類去調用,而不是實例
console.log("tell");
}
}
Parent.tell(); // tell
//=====================================
// 七、類的靜態屬性:
class Parent {
//定義一個類
constructor(name = "小白") {
this.name = name;
}
static tell() {
// 靜態方法:經過類去調用,而不是實例
console.log("tell"); // tell
}
}
Parent.type = "test"; // 定義靜態屬性
console.log("靜態屬性", Parent.type); // 靜態屬性 test
let v_parent = new Parent();
console.log(v_parent); // {name: "小白"} 沒有tell方法和type屬性
複製代碼
es6 是一個新的標準,它包含了許多新的語言特性和庫,是 JS 最實質性的一次升級。
好比'箭頭函數'、'字符串模板'、'generators(生成器)'、'async/await'、'解構賦值'、'class'等等,還有就是引入 module 模塊的概念。
箭頭函數可讓 this 指向固定化,這種特性頗有利於封裝回調函數
this
對象是定義是所在的對象,而不是使用時所在的對象new
命令function postJson(url, data) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.onreadystatuschange = () => {
if(xhr.readyState !== 4) return;
if(xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject('請求失敗')
}
}
xhr.send(JSON.stringify(data));
})
}
複製代碼
key給每一個vnode(虛擬節點)增長一個惟一ID,在更新組件是判斷兩個節點是否相同。相同就複用,不相同就刪除舊建立新的。
雖然帶上key會增長開銷,可是對於用戶來講基本感覺不到差距,並且能保證組件狀態正確。
不帶key時節點可以複用,省去了銷燬/建立組件的開銷,同時只須要修改DOM文本內容而不是移除/添加節點。
這種模式diff速度可能會更快,但也會帶來一些隱藏的反作用,好比可能不會產生過渡效果,或者在某些節點有綁定數據(表單)狀態,會出現狀態錯位。 這種模式只適用於渲染簡單的無狀態組件
vue.js 是採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。
具體步驟:
第一步:須要 observe
的數據對象進行遞歸遍歷,包括子屬性對象的屬性,都加上 setter
和 getter
這樣的話,給這個對象的某個值賦值,就會觸發setter
,那麼就能監聽到了數據變化
第二步:compile
解析模板指令,將模板中的變量替換成數據,而後初始化渲染頁面視圖,並將每一個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變更,收到通知,更新視圖
第三步:Watcher
訂閱者是Observer
和Compile
之間通訊的橋樑,主要作的事情是:
update()
方法第四步:MVVM做爲數據綁定的入口,整合Observer、Compile和Watcher三者,經過Observer來監聽本身的model數據變化,經過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通訊橋樑,達到數據變化 -> 視圖更新;視圖交互變化(input) -> 數據model變動的雙向綁定效果。
Vue生命週期一共分爲8個階段
beforeCreated
階段,實例的$el
、data
和methods
都未初始化。this
指向建立的實例created
階段,實例的data
和methods
都初始化完成,但 DOM
節點還未掛載,不能訪問到$el
屬性,$ref
屬性爲空數組beforeMount
階段,實例找到相對應的template
並編譯成render
函數mouted
階段,實例將el
掛載到DOM
上,能夠獲取到DOM
節點,$ref
屬性能夠訪問data
變化時,會觸發beforeUpdate
和updated
destroy
方法後,data
的改變不會再觸發周期函數,此時Vue實例已經解除了事件監聽
和DOM綁定
,但DOM結構依然存在。on
自定義事件綁定方法來接收值,子組件經過$emit觸發自定義事件傳遞參數給父組件keep-alive
的做用是什麼小圖片轉base64
靜態下圖片使用雪碧圖
生成環境屏蔽sourceMap
開啓gzip壓縮文件,減小文件大小
第三方依賴按需加載
vue-router懶加載/異步路由
代碼優化
骨架屏
State
,Getter
,Mutation
,Action
,Module
state
爲單一狀態數,是數據源存放的地方(對應Vue
對象裏的data
),存放的數據是響應式的,Vue組件從store
讀取數據,當store
中的數據發生變化則依賴數據的組件也會發生變化。mapState
輔助函數把state
映射到組件的computed
計算屬性上store.commit
store.dispatch
觸發異步組件
component: resolve => require(['../components/PromiseDemo'], resolve)
import
const ImportFuncDemo2 = () => import('../components/ImportFuncDemo2')
component: ImportFuncDemo2
webpackrequire.ensure()
component: resolve => require.ensure([], () => resolve(require('../components/PromiseDemo')), 'demo')
參考:vue項目按需加載
router-link
建立a標籤來定義導航連接router.push({ path: 'home' })
全局守衛
router.beforeEach
router.beforeResolve
(2.5.0 新增)router.afterEach
路由獨享守衛
beforeEnter
組件守衛
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
Vue源碼
項目中遇到的問題
微信小程序項目結構主要有四個文件類型
WXML
: WeiXin Markup Language
是框架設計的一套標籤語言,結合基礎組件、事件系統,能夠構建出頁面的結構。內部主要是微信本身定義的一套組件WXSS
: WeiXin Style Sheets
是一套樣式語言,用於描述 WXML
的組件樣式js
: 邏輯處理,網絡請求json
: 小程序設置,如頁面註冊,頁面標題及tabBar
主要文件
app.json
必需要有這個文件,若是沒有這個文件,項目沒法運行,由於微信框架把這個做爲配置文件入口,整個小程序的全局配置。包括頁面註冊,網絡設置,以及小程序的 window
背景色,配置導航條樣式,配置默認標題app.js
必需要有這個文件,沒有也是會報錯!可是這個文件建立一下就行 什麼都不須要寫之後咱們能夠在這個文件中監聽並處理小程序的生命週期函數、聲明全局變量app.wxss
可選微信小程序採用
JavaScript
、WXML
、WXSS
三種技術進行開發,本質就是一個單頁面應用,全部的頁面渲染和事件處理,都在一個頁面內進行,但又能夠經過微信客戶端調用原生的各類接口
微信的架構,是數據驅動的架構模式,它的
UI
和數據是分離的,全部的頁面更新,都須要經過對數據的更改來實現
小程序分爲兩個部分
webview
和appService
。其中webview
主要用來展示UI
,appService
有來處理業務邏輯、數據及接口調用。它們在兩個進程中運行,經過系統層JSBridge
實現通訊,實現UI
的渲染、事件的處理
小程序直接 this.data
的屬性是不能夠同步到視圖的,必須調用:
this.setData({
// 這裏設置
})
複製代碼
WXSS
和CSS
相似,不過在CSS
的基礎上作了一些補充和修改
rpx
rpx
是響應式像素,能夠根據屏幕寬度進行自適應。規定屏幕寬爲 750rpx
。如在 iPhone6
上,屏幕寬度爲 375px
,共有 750
個物理像素,則 750rpx = 375px = 750
物理像素
@import
標識符來導入外聯樣式。@import
後跟須要導入的外聯樣式表的相對路徑,用;表示語句結束/** index.wxss **/
@import './base.wxss';
.container{
color: red;
}
複製代碼
app.js
文件中定義全局變量 globalData
, 將須要存儲的信息存放在裏面// app.js
App({
// 全局變量
globalData: {
userInfo: null
}
})
複製代碼
使用的時候,直接使用 getApp()
拿到存儲的信息
wx.navigateTo
與 wx.redirectTo
的時候,能夠將部分數據放在 url
裏面,並在新頁面 onLoad
的時候初始化//pageA.js
// Navigate
wx.navigateTo({
url: '../pageD/pageD?name=raymond&gender=male',
})
// Redirect
wx.redirectTo({
url: '../pageD/pageD?name=raymond&gender=male',
})
// pageB.js
...
Page({
onLoad: function(option){
console.log(option.name + 'is' + option.gender)
this.setData({
option: option
})
}
})
複製代碼
須要注意的問題:
wx.navigateTo
和 wx.redirectTo
不容許跳轉到 tab
所包含的頁面
onLoad
只執行一次
Storage
相關onLoad
頁面加載時觸發。一個頁面只會調用一次,能夠在 onLoad
的參數中獲取打開當前頁面路徑中的參數onShow()
頁面顯示/切入前臺時觸發onReady()
頁面初次渲染完成時觸發。一個頁面只會調用一次,表明頁面已經準備穩當,能夠和視圖層進行交互onHide()
頁面隱藏/切入後臺時觸發。 如 navigateTo
或底部 tab
切換到其餘頁面,小程序切入後臺等onUnload()
頁面卸載時觸發。如 redirectTo
或 navigateBack
到其餘頁面時詳見 生命週期回調函數
wx.request({
url: 'test.php', //僅爲示例,並不是真實的接口地址
data: {
x: '' ,
y: ''
},
success: function(res) {
console.log(res.data)
}
})
// promise
複製代碼
參考 這裏
一、提升頁面加載速度
二、用戶行爲預測
三、減小默認 data
的大小
四、組件化方案
優點
App
低缺點
App
要深不少小程序支持大部分
ES6
語法
Promise
異步若是開發者擁有多個移動應用、網站應用、和公衆賬號(包括小程序),可經過
unionid
來區分用戶的惟一性,由於只要是同一個微信開放平臺賬號下的移動應用、網站應用和公衆賬號(包括小程序),用戶的unionid
是惟一的。換句話說,同一用戶,對同一個微信開放平臺下的不一樣應用,unionid
是相同的
config
中的 window
配置 enablePullDownRefresh
Page
中定義 onPullDownRefresh
鉤子函數,到達下拉刷新條件後,該鉤子函數執行,發起請求方法wx.stopPullDownRefresh
中止下拉刷新參考 這裏
相同點:首先他們都是做爲點擊事件函數,就是點擊時觸發。在這個做用上他們是同樣的,能夠不作區分
不一樣點:他們的不一樣點主要是 bindtap
是不會阻止冒泡事件的,catchtap
是阻值冒泡的
wx.navigateTo()
, wx.redirectTo()
, wx.switchTab()
, wx.navigateBack()
, wx.reLaunch()
的區別wx.navigateTo()
:保留當前頁面,跳轉到應用內的某個頁面。可是不能跳到 tabbar
頁面wx.redirectTo()
:關閉當前頁面,跳轉到應用內的某個頁面。可是不容許跳轉到 tabbar
頁面wx.switchTab()
:跳轉到 abBar
頁面,並關閉其餘全部非 tabBar
頁面wx.navigateBack()
關閉當前頁面,返回上一頁面或多級頁面。可經過 getCurrentPages()
獲取當前的頁面棧,決定須要返回幾層wx.reLaunch()
:關閉全部頁面,打開到應用內的某個頁面JS 採用的是雙精度版本
咱們計算機的信息所有轉化爲二進制進行存儲的,那麼0.1的二進制表示的是一個無限循環小數, 該版本的 JS 採用的是浮點數標準須要對這種無限循環的二進制進行截取,從而致使了精度丟失, 形成了0.1再也不是0.1,截取以後0.1變成了 0.100...001,0.2變成了0.200...002。因此二者相加的數大於0.3。
由於在輸入內容進行轉換的時候,二進制轉換成十進制,而後十進制轉換成字符串, 在這個轉換的過程當中發生了取近似值,因此打印出來的是一個近似值。
// 特定需求頁面,好比評論頁面,輸入框在頂部之類的
const interval = setInterval(function() {
document.body.scrollTop = 0;
}, 100)
// 注意關閉頁面或者銷燬組件的時候記得清空定時器
clearInterval(interval);
複製代碼
/**使用postcss的autoprefixer插件,自動添加瀏覽器內核前綴, 而且增長更低瀏覽器版本的配置,自動添加flex老版本的屬性和寫法**/
autoprefixer({
browsers: [
'iOS >= 6', // 特殊處理支持低版本IOS
'Safari >= 6', // 特殊處理支持低版本Safari
],
}),
複製代碼
<meta content="telephone=no" name="format-detection" />
複製代碼
<meta content="email=no" name="format-detection" />
複製代碼
緣由:click事件要等待是不是雙擊事件,會有300ms的延遲
解決:使用touchstart/touchend或者使用zepto的tap事件替代click