【面試向】極簡前端知識點(不斷更新)
CS / BS 架構
CS 客戶端 / 伺服器架構
BS 瀏覽器 / 伺服器架構
RESTful
將URL看作資源,URL 中用 名詞 表示。各種操作透過不同的請求方式來識別。目的是 只看介面和請求方式就能知道這是幹嘛的,比如
順便知道一下,除了 GET,POST 外,還有 HEAD, PUT,PATCH,DELETE 等請求方式
GET /api/libraries/123/books?keyword=game&sort=price&limit=10&offset=0
含義就是:從一堆圖書館中,找到第 123 個圖書館的書,在書裡查詢所有關鍵詞為 game ,以價格排序,從 0 開始的前 10 條資料
冪等 / 非冪等
冪等:多次請求結果一樣,比如一條更新的請求,將數值更新為 5,執行幾次都是更新為 5;
非冪等:新增。原來有三條資料,隨著新增操作,資料數也隨之增加
請求
-
專案中的一個查詢請求(這裡從 RESTful 的角度講,不應該用 POST)
一次請求
關於 meta 標籤的 content="width=device-width"
目前總結的理解方式為:讓你當前正在寫的 html 的寬度等於裝置寬度
Object.freeze() 凍結
無法新增屬性,但對於非基本型別(Array,Object)的屬性依舊可以新增。
徹底凍結一個物件(一凍到底)
var obj = { arr: [1, 2] }function freezen(obj) { Object.freeze(obj); Object.keys(obj).forEach(function(it, i) { if(typeof obj[it] === 'object') { freezen(obj[it]) } }) } freezen(obj)
類陣列轉陣列
Array.from(likeArr)
[...likeArr]
Array.prototype.slice.call()
關於 var let 和 for 迴圈
for 迴圈條件中 var 宣告的變數等同於全域性變數
for 迴圈條件中 let 宣告的變數不是全域性變數(全域性中取不到),算作是 for 迴圈 {} 的 父級變數,不會影響 {} 中 let 宣告同樣的變數;這一點跟函式不一樣,引數宣告瞭 x ,函式體中需要注意 暫時性死區
var 宣告的全域性變數是 window 物件的一個屬性,但 let 宣告的物件不是
map,foreach,$.each,each
# map陣列.map(function(值,下標,陣列) { console.log(arguments) })# foreach陣列.foreach(function(值,下標,陣列) { console.log(arguments) })# $.each(jQuery)$.each(任何可遍歷的物件, function(key, value) { console.log(arguments) })# each(jQuery)DOM物件.each(function(key, value) { console.log(arguments) })
箭頭函式兩句話攻略
-
箭頭函式沒有自己的 this,arguments,super,由於沒有自己的 this,也就不能使用 bind,call,apply 更改 this 的指向,但不代表箭頭函式不能呼叫那三個方法;
let obj = { name:'lky' } let arrFn = () => { console.log(this); } function commonFn(){ console.log(this) } arrFn(); // window arrFn.call(obj); // window (可以呼叫,但沒法改變 this 指向) commonFn(); // window commonFn.call(obj); // obj
箭頭函式體只有一條語句時自帶 return,且 return 可省略
事件委託
提高效能,有牌面
祖先.addEventListener('click', function(e){ var target = e.target || e.srcElement; if (!!target && target.nodeName.toLowerCase()==='目標元素') { console.log(target.innerHTML) } })
關於獲取屬性的 []
和 .
的區別
[]
可以用變數,數字和保留字獲取屬性,ES6 還允許表示式
Object.assign()
Object.assign(目標物件,源...)
合併 可列舉 的 自身 屬性
淺複製,即引用時源改變了則目標也改變
Object.defineProperty() / Object.defineProperties() 新增屬性描述
Object.defineProperty(目標物件,屬性名,{屬性描述})
Object.defineProperty(obj, "key", { enumerable: false, configurable: false, writable: false, value: "static"});
Object.defineProperties(目標物件,屬性組及屬性描述)
var obj = {};Object.defineProperties(obj, { 'property1': { value: true, writable: true }, 'property2': { value: 'Hello', writable: false } // etc. etc.});
目標物件.hasOwnProperty()
目標物件.hasOwnProperty(目標屬性)
obj 自身 是否含有目標屬性,不是原型上,返回布林值
Object.getPrototypeOf() / Object.setPrototypeOf()
Object.getPrototypeOf(目標物件)
獲取目標物件的原型Object.setPrototypeOf(目標物件,物件原型)
設定目標物件的原型
Object.create()
Object.create(新物件的原型,{新物件的屬性:{屬性描述}})
(後者可選)
# 建立新物件 clone,其原型為 obj 的原型,新增 newProp 屬性const obj = { 'a': 'aa', 222: 3123, 'unenumerable': '不可列舉屬性'} const clone = Object.create(Object.getPrototypeOf(obj), { 'newProp': { value: '新值', enumerable: true } }); Object.getOwnPropertyDescriptors(clone) // newProp:{value: undefined, writable: false, enumerable: true, configurable: false} // 未指定的屬性均為 false
也可以:
const obj = { 'a': 'aa', 222: 3123, 'unenumerable': '不可列舉屬性'}Object.defineProperty(obj, 'unenumerable', { enumerable: false})const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) );Object.getOwnPropertyDescriptors(clone)
結果:
結果
這樣就等同於 淺克隆 了一個 obj 物件 clone
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor(目標物件,目標物件屬性)
獲取目標物件自身的屬性描述
const obj = { 'a': 'aa', 222: 3123 } Object.getOwnPropertyDescriptor(obj, 'a') // {value: "aa", writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptors(目標物件)
獲取目標物件自身的全部屬性描述
const obj = { 'a': 'aa', 222: 3123, 'unenumerable':'不可列舉'} Object.defineProperty(obj,'unenumerable',{enumerable:false}) // 設定為不可列舉 Object.getOwnPropertyDescriptors(obj) /** * 222: {value: 3123, writable: true, enumerable: true, configurable: true} * a: {value: "aa", writable: true, enumerable: true, configurable: true} * unenumerable: {value: "不可列舉", writable: true, enumerable: false, configurable: true} **/
for ... in / for ... of / Object.keys / Object.values / Object.entries / Object.getOwnPropertyNames(obj)
for ... in 自身及繼承 的所有 可列舉 屬性,不含 Symbol
Object.keys 返回陣列,自身 所有 可列舉 屬性(不含 Symbol 屬性)的鍵名
Object.getOwnPropertyNames(obj) 自身,可列舉 及 不可列舉 的屬性名(不含 Symbol)
名稱 | 目標 | 類別 |
---|---|---|
for...in... | 自身及繼承的屬性名或索引 | 可列舉 |
Object.keys | 自身 | 可列舉 |
Object.values | 自身 | 可列舉 |
Object.entries | 自身 | 可列舉 |
Object.getOwnPropertyNames(obj) | 自身 | 可列舉 / 不可列舉 |
for ... of ...:遍歷具有 Symbol.iterator 介面物件自身具有數字索引的值
for ... in ...:遍歷物件自身及原型上可列舉的屬性名或索引
let arr = [3, 5, 7]; arr.foo = 'hello'; Array.prototype.baz='world';for (let i in arr) { console.log(i); // "0", "1", "2", "foo", "baz"}for (let i of arr) { console.log(i); // "3", "5", "7"}
建構函式原型物件上的方法和屬性是給例項呼叫的,建構函式本身無法呼叫
Set / Map 資料結構
Set:沒有重複值的 Array
Map:常規的 Object 是key:value形式,Map 支援 Object 等作為 key
外部指令碼 標籤及 defer,async
渲染引擎遇到
標籤就會停下來,等到執行完指令碼,再繼續向下渲染。如果是外部指令碼,還必須加入指令碼下載的時間。
// module_test.jslet delay = +new Date(); console.log('外部指令碼');while(+new Date() - delayconsole.log('本地指令碼')// 結果外部指令碼 ---- 3s later ---- 本地指令碼
-
區別:
區別
類別 | 解釋 |
---|---|
script | 解析 HTML - 下載 script - 解析 script - 繼續解析 HTML |
defer | 解析 HTML - 下載 script - 繼續解析 HTML - 解析 script |
async | 解析 HTML - 下載 script(此時仍在解析 HTML) - 解析 script - 解析 HTML |
解決 jQuery 中 $ 衝突
jQuery.noConflict()
var j = jQuery.noConflict();// 基於 jQuery 的程式碼j("div p").hide();// 基於其他庫的 $() 程式碼$("content").style.display = 'none';
解決 jQuery 中 $ 原理
-
方法加在 jQuery 上,然後透過
window.jQuery = window.$ = jQuery
陣列操作 / 字串操作
陣列操作
名稱 | 用法 | 返回 |
---|---|---|
concat() | arrayObject.concat(arrayX,arrayX,......,arrayX) | 新陣列 |
join() | arrayObject.join(分隔符) | 字串 |
pop() | arrayObject.pop() | 最後一個元素 |
push() | arrayObject.push(newelement1,newelement2,....,newelementX) | 新增後的長度 |
reverse() | arrayObject.reverse() | 改變原陣列 |
shift() | arrayObject.shift() | 第一個元素 |
slice() | arrayObject.slice(start,end) | 不改變原陣列,返回新陣列,支援負數 |
sort() | arrayObject.sort(function) | 改變原陣列 |
splice() | arrayObject.splice(index,howmany,item1,.....,itemX) | 改變原陣列 |
字串操作
名稱 | 描述 | 返回 |
---|---|---|
charAt() | 返回在指定位置的字元 | |
concat() | 連線字串 | |
indexOf() | 檢索字串 | 布林值 |
match() | 找到一個或多個正規表示式的匹配 | 布林值 |
replace() | 替換與正規表示式匹配的子串 | 新字串 |
search() | 檢索與正規表示式相匹配的值 | 第一個匹配子串的起始位置 |
slice() | 提取字串的片斷,並在新的字串中返回被提取的部分 | |
split() | 把字串分割為字串陣列 | |
substr() | 從起始索引號提取字串中 指定數目 的字元 | |
substring() | 提取字串中兩個 指定的索引號 之間的字元 |
迴流(reflow)和重繪(repaint)
迴流:更改了 DOM 結構(display:none),迴流也會觸發重繪
重繪:變個顏色,加個邊框之類的
表格的 cellpadding 和 cellspacing
cellpadding 和 cellspacing
確切的判斷一個物件 / 陣列 / null 等的型別
-
Array.isArray()
或Object.prototype.toString.call()==='[object Object]'Object.prototype.toString.call()==='[object Array]'Object.prototype.toString.call()==='[object Set]'Object.prototype.toString.call()==='[object Map]'Object.prototype.toString.call()==='[object Symbol]'Object.prototype.toString.call()==='[object String]'Object.prototype.toString.call()==='[object Null]'Object.prototype.toString.call()==='[object Undefined]' Object.prototype.toString.call()==='[object Boolean]'Object.prototype.toString.call()==='[object Number]'
判斷
NaN
用isNaN()
,或者Object.is()
=== 和 Object.is
區別 | === | Object |
---|---|---|
+0,-0 | true | false |
NaN,NaN | false | true |
原生 ajax
get
var xhr = new XMLHttpRequest(); xhr.open('get','getStar.php?starName='+name,true); xhr.send(); xhr.onreadystatechange = function () { if (xhr.readyState==4 && xhr.status==200) { console.log(xhr.responseText); //輸入相應的內容 } }
post
var xhr = new XMLHttpRequest(); xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xhr.open('post', '02.post.php' ,true); xhr.send('name=fox&age=18'); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { console.log(xhr.responseText); } };
建立物件的幾種模式
工廠模式:無法判斷物件型別(對比建構函式模式)
function createPerson(){ var Child = new Object(); Child.name = "欲淚成雪"; Child.age = "20"; return Child; };var x = createPerson();
建構函式模式:可以透過
x instanceof Person
得知x
是Person
,而工廠模式則無法知道x
是Person
;
function Person(){ this.name = "欲淚成雪"; this.age = "20"; this.say = function(){ alert("Hello!") } };function Fruit(){ this.name = "水果"; this.price = "13"; };var x = new Person();var y = new Fruit();
但這種模式每次例項化都會重新初始化屬性 arr
和方法 say
,並且不同例項的 arr
和 say
並不是一個玩意
function Person() { this.name = "欲淚成雪"; this.age = "20"; this.arr = [0,1]; this.say = function(){ alert("Hello") } };var Tom = new Person();var Jerry = new Person();console.log(Tom.name === Jerry.name) // trueconsole.log(Tom.arr === Jerry.arr) // falseconsole.log(Tom.say === Jerry.say) // false
原型模式:如下這種形式,每個例項的屬性和方法都相同
function Person(){};Parent.prototype.name = "欲淚成雪";Parent.prototype.age = "20";var x = new Person();
混合模式(構造 + 原型)
function Person(){ this.name = "欲淚成雪"; this.age = 22; }; Person.prototype.lev = function(){ return this.name; };var x = new Person();
get / post
get | post |
---|---|
URL中傳送 | 訊息主體 |
可快取 | 不可快取 |
可歷史記錄 | 不可保留為歷史記錄 |
可書籤 | 不可書籤 |
有長度限制 | 沒有長度限制 |
關於 getElementsByTagName 和 querySelectorAll
querySelectorAll 可直接放選擇器 '.abc'
querySelectorAll 效能不如前者
querySelectorAll 靜態查詢
- aaa
- ddd
- ccc
HTML5 新特性
新增選擇器 document.querySelector、document.querySelectorAll
拖拽釋放(Drag and drop) API
媒體播放的 video 和 audio
本地儲存 localStorage 和 sessionStorage
離線應用 manifest
桌面通知 Notifications
語意化標籤 article、footer、header、nav、section
增強表單控制元件 calendar、date、time、email、url、search
地理位置 Geolocation
多工 webworker
全雙工通訊協議 websocket
歷史管理 history
跨域資源共享(CORS) Access-Control-Allow-Origin
頁面可見性改變事件 visibilitychange
跨視窗通訊 PostMessage
Form Data 物件
繪畫 canvas
響應式佈局
CSS3
@media screen and (min-width:960px) and (max-width:1200px){ body{background:yellow;} }
也可以這樣
鏈式呼叫原理
function Foo(){} Foo.prototype = { css:function(){ console.log("設定css樣式"); return this; }, show:function(){ console.log("將元素顯示"); return this; }, hide:function(){ console.log("將元素隱藏"); } };var foo = new Foo(); foo.css().css().show().hide();
flex
關鍵詞:容器,專案,主軸,交叉軸
容器和專案是父子集
容器
display:flex
後,float
,clear
,vertical-align
失效容器
屬性名 | 描述 |
---|---|
flex-direction | 主軸的方向 |
flex-wrap | 如何換行 |
flex-flow | 上兩個的縮寫 |
justify-content | 專案在主軸的對齊方式 |
align-items | 專案在交叉軸的對齊方式 |
專案
屬性名 | 描述 |
---|---|
order | 專案排列順序,越小越靠前 |
flex-grow | 專案放大比例 |
flex-shrink | 專案縮小比例 |
flex-basis | 屬性定義了在分配多餘空間之前,專案佔據的主軸空間 |
flex | 上三個的縮寫 |
align-self | 專案在交叉軸上的對齊方式 |
-
相容
flex 相容
vue 虛擬 DOM
直接操作 DOM 成本高,透過 JavaScript 建立一個記錄 DOM 的物件,之後一次渲染這個物件
先定義一個建構函式
//虛擬dom,引數分別為標籤名、屬性物件、子DOM列表var VElement = function(tagName, props, children) { //保證只能透過如下方式呼叫:new VElement if (!(this instanceof VElement)) { return new VElement(tagName, props, children); } //可以透過只傳遞tagName和children引數 if (util.isArray(props)) { children = props; props = {}; } //設定虛擬dom的相關屬性 this.tagName = tagName; this.props = props || {}; this.children = children || []; this.key = props ? props.key : void 666; var count = 0; util.each(this.children, function(child, i) { if (child instanceof VElement) { count += child.count; } else { children[i] = '' + child; } count++; }); this.count = count; }
生成例項,用 JavaScript 表示 DOM 結構
var vdom = velement('div', { 'id': 'container' }, [ velement('h1', { style: 'color:red' }, ['simple virtual dom']), velement('p', ['hello world']), velement('ul', [velement('li', ['item #1']), velement('li', ['item #2'])]), ]);
上面的 JavaScript 程式碼就代表瞭如下的 DOM 結構
simple virtual dom
hello world
- item #1
- item #2
Vue 的計算屬性 computed 和監聽屬性 watch
computed 可以新建一個屬性
watch 只能用 data 中已有的屬性
{{ fullName }}// watchvar vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { // firstName 和 lastName 都是 data 中已有的屬性 this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } } })// computedvar vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { // fullName 在 data 中並沒有 return this.firstName + ' ' + this.lastName } } })
margin 塌陷
父子集關係:
1.父級overflow:hidden
2.父級新增border
3.父級新增padding
兄弟集關係:
1.任意兄弟新增display:inline-block
2.下面的新增float:left
圖片下的小空白
圖片下小空白
紅框為父級
,而 圖片和文字 都是以父級的基線baseline
對齊,基線就是xxx
的下邊界,因此修改圖片的對齊方式vertical-align
即可圖片設定:
1.display:block
2.vertical-align:top父級設定:
1.font-size:0父子同時設定:
1.float:left修改 span 的 vertical-align
BFC 是什麼?
可以理解為定義一個環境,在這個環境內的元素不論怎麼調整都不會影響環境外部的樣式
形成條件
1.浮動元素,float 除 none 以外的值;
2.絕對定位元素,position(absolute,fixed);
3.display 為以下其中之一的值 inline-blocks,table-cells,table-captions;
4.overflow 除了 visible 以外的值(hidden,auto,scroll)
公有方法,私有方法,靜態屬性
公有方法:例項可以呼叫
私有方法:只能在建構函式內呼叫,一般用於對建構函式內的屬性或方法進行修改
function Foo(){ // 公有方法 this.name = function(){ alert("Hello") } // 私有方法 function age(){ alert("World") } }
靜態屬性:只能由建構函式自己呼叫,而不能被例項呼叫的屬性
# ES5function Foo(){} Foo.age = 12; // 靜態屬性Foo.getAge = function(){ // 靜態方法 console.log(this.age) }# ES6 class Foo{ static age(){ // 靜態方法 console.log(12) } } Foo.sex = 'boy' // 靜態屬性(ES6 類內沒有靜態屬性)
ES6 繼承
class Son extends Dad {}
資料屬性 / 訪問器屬性
資料屬性:
1.configurable
2.enumerable
3.writable
4.value訪問器屬性:
1.configurable
2.enumerable
3.get
4.set
實現一個深複製
function deepClone(obj) { var newObj = obj instanceof Array ? [] : {}; //obj屬於基本資料型別,直接返回obj if(typeof obj !== 'object') { return obj; } else { //obj屬於陣列或物件,遍歷它們 for(var i in obj) { newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]):obj[i]; } } return newObj; }
取出巢狀陣列的全部數值
這個思路跟上一個很像,所以放在一起
// 常規版let newArr = [];function getArr(arr) { for(let i = 0; i
generator 版
const arr = ["a", "b", "c", "d", ["aa", "bb"]];function* tree(item) { if(Array.isArray(item)) { // 如果是陣列,就依次取出,再呼叫自己 for(var i = 0; i
克隆物件及原型鏈
// 寫法一const clone1 = Object.assign( Object.create(Object.getPrototypeOf(obj)), obj );// 寫法二const clone2 = Object.create( Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj) )
幾道面試題
一直以來我都認為這種題意義不大,然而每次遇到這種題時卻發現答案總是搖擺不定,歸根結底還是基礎不夠紮實,因此只好強忍著噁心再來一點點分析
function create(obj){ obj.name = '粉粉'; obj = new Object(); obj.name = '嬌嬌'; }var person = new Object(); create(person);console.log(person.name); // 粉粉
這個也得改一下,先是把函式改成這樣:
function create() { var obj; obj.name = '粉粉'; obj = new Object(); obj.name = '嬌嬌'; }
而呼叫
create(person)
變成這樣:
function create() { var obj = person; // 此時 obj 和 person 指向一塊記憶體 obj.name = '粉粉'; // 為同一塊記憶體新增屬性,這是 obj 和 person 共有的屬性 obj = new Object(); // 然後讓 obj 指向另一塊記憶體 obj.name = '嬌嬌'; // obj 已經指向另一塊記憶體,再為 obj 新增屬性當然跟 person 無關了}
var a = '小旭'; (function(){ console.log(typeof a) // undefined console.log(typeof fun1) // function console.log(typeof fun2) // undefined var a = '旭旭'; function fun1(){}; var fun2 = function(){} console.log(typeof a); // string console.log(typeof fun1); // function console.log(typeof fun2); // function})(window)
這題主要是變數提升,與下面這種寫法是等價的,再看不懂就去面壁
var a = '小旭'; (function(){ var a; function fun1(){}; var fun2; console.log(typeof a) // undefined console.log(typeof fun1) // function console.log(typeof fun2) // undefined a = '旭旭'; fun2 = function(){} console.log(typeof a); // string console.log(typeof fun1); // function console.log(typeof fun2); // function})(window)
var foo = { bar:function(){ return this.baz; }, baz:1}; (function(){ console.log(arguments[0]()); // undefined console.log(foo.bar()); // 1 console.log(arguments[0].call(foo)); // 1})(foo.bar)
三個的
this
分別指向arguments
,foo
,foo
function Foo(){ getName = function(){console.log(1);} return this; } Foo.getName = function(){console.log(2);} Foo.prototype.getName = function(){console.log(3);}var getName = function(){console.log(4);}function getName(){console.log(5);} Foo.getName(); // 2getName(); // 4Foo().getName(); // 1getName(); // 1new Foo.getName(); // 2new Foo().getName(); // 3
也是先把變數提升處理了,改成下面這種,注意:同樣是宣告提升,但變數提升在函式宣告之上
1.列印靜態方法,沒啥說的
2.全域性的getName
一共賦了三次值(兩次在全域性賦值,一次在區域性賦值),第一次:function getName(){console.log(5);}
,第二次:function getName();{console.log(4);}
;第三次為區域性賦值:function Foo(){ getName = function(){console.log(1);} return this; }
3.Foo()
建構函式也可以當做普通函式呼叫,Foo()
呼叫後,內部又對全域性的getName
重新賦值為function(){console.log(1);}
返回的this
指向window
,相當於呼叫window.getName()
,而此時的getName()
在呼叫Foo()
後已被賦值為1
4.window.getName()
就等於在全域性直接呼叫getName()
5.不要想太多,反正Foo.getName
就是個普通函式,把Foo.getName
看做abc
就完了,這裡只是例項化的過程中伴隨了執行的操作罷了
6.相當於例項.getName()
,呼叫的是原型上的方法Foo.prototype.getName = function(){console.log(3);}
var getName;function Foo(){ getName = function(){console.log(1);} return this; }function getName(){console.log(5);} Foo.getName = function(){console.log(2);} Foo.prototype.getName = function(){console.log(3);} getName = function(){console.log(4);} Foo.getName(); // 2getName(); // 4Foo().getName(); // 1getName(); // 1new Foo.getName(); // 2new Foo().getName(); // 3
var fullName = 'language';var obj = { fullName:'javascript', prop:{ getFullName:function(){ return this.fullName; } } }console.log(obj.prop.getFullName()); // undefinedvar test = obj.prop.getFullName;console.log(test()); // language
第一個
this
指向的是obj.prop
第二個列印可改成如下,
this
指向window
var fullName = 'language';var obj = { fullName:'javascript', prop:{ getFullName:function(){ return this.fullName; } } }console.log(obj.prop.getFullName()); // undefinedvar test = function(){ return this.fullName }console.log(test());
var name = 'Jerry';var Tom = { name:'Tom', show:function(){ console.log(this.name) }, wait:function(){ var fun = this.show; fun(); } }; Tom.wait(); // Jerry
因為呼叫
Tom.wait()
時,this
指向Tom
,因此wait
屬性中的this.show
實際上就是Tom.show
,那就可以改成下面這種:
var name = 'Jerry';var Tom = { name:'Tom', show:function(){ console.log(this.name) }, wait:function(){ function fun(){ console.log(this.name) // 這裡的 this 指向 window } fun(); } }; Tom.wait(); // Jerry
setTimeout(function() { // 定時器1 var end = +new Date(); console.log(end - start) }, 1000) setTimeout(function() { // 定時器2 console.log('哈哈哈') }, 0)console.time('circle')let delay = +new Date();while(+new Date() - delay
結果
分析:
1.想像任務佇列是個時間軸
2.定時器1:非同步任務,放到任務佇列 1000ms 的時間點上。
3.定時器2:非同步任務,放到任務佇列 0ms 的時間點上
4.同步阻塞 1500ms ,此時,定時器1 的任務也已經從 1000ms 的時間點移至緊隨 定時器2 的時間點,也就是說,此時如果 定時器2 執行,定時器1 也將緊隨其後執行,不需再等待 1000ms。
5.執行同步任務var start = +new Date();
執行完後,執行棧已空,可以開始執行任務佇列中的任務,先執行定時器2,然後 立刻 執行定時器1
var value = 1;function foo() { console.log(value); }function bar() { var value = 2; foo(); } bar(); // 1
JavaScript 採用詞法作用域(靜態作用域),函式的作用域在定義時已經確定,
foo
的定義時的value
為全域性變數函式定義時確定作用域,函式呼叫時先建立執行上下文,在具體的執行過程中再進行執行上下文初始化
實現 bind 方法
bind / call 的區別
bind
返回函式,call
立即呼叫
var obj = { name : 24}function fn(){ console.log(this.name); } fn.bind(obj)() // 24fn.call(obj) // 24
new 運算子做了什麼
1.建立一個新物件
2.將建構函式的 this 指向新物件
3.執行建構函式
4.返回新物件function Foo(){ this.name = '我亦飄零'; };var obj = {}; obj.__proto__ = Foo.prototype; Foo.call(obj)
函式柯里化
常見的瀏覽器相容問題 js / css
* png24位的圖片在iE6瀏覽器上出現背景,解決方案是做成PNG8.也可以引用一段指令碼處理. * 瀏覽器預設的margin和padding不同。解決方案是加一個全域性的*{margin:0;padding:0;}來統一。 * IE6雙邊距bug:塊屬性標籤float後,又有橫行的margin情況下,在ie6顯示margin比設定的大。 * 浮動ie產生的雙倍距離(IE6雙邊距問題:在IE6下,如果對元素設定了浮動,同時又設定了margin-left或margin-right,margin值會加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;} 這種情況之下IE會產生20px的距離,解決方案是在float的標籤樣式控制中加入 ——_display:inline;將其轉化為行內屬性。(_這個符號只有ie6會識別) * 漸進識別的方式,從總體中逐漸排除區域性。 首先,巧妙的使用“9”這一標記,將IE遊覽器從所有情況中分離出來。 接著,再次使用“+”將IE8和IE7、IE6分離開來,這樣IE8已經獨立識別。 css .bb{ background-color:#f1ee18;/*所有識別*/ .background-color:#00deff9; /*IE6、7、8識別*/ +background-color:#a200ff;/*IE6、7識別*/ _background-color:#1e0bd1;/*IE6識別*/ } * IE下,可以使用獲取常規屬性的方法來獲取自定義屬性, 也可以使用getAttribute()獲取自定義屬性; Firefox下,只能使用getAttribute()獲取自定義屬性. 解決方法:統一透過getAttribute()獲取自定義屬性. * IE下,event物件有x,y屬性,但是沒有pageX,pageY屬性; Firefox下,event物件有pageX,pageY屬性,但是沒有x,y屬性. * 解決方法:(條件註釋)缺點是在IE瀏覽器下可能會增加額外的HTTP請求數。 * Chrome 中文介面下預設會將小於 12px 的文字強制按照 12px 顯示, 可透過加入 CSS 屬性 -webkit-text-size-adjust: none; 解決. * 超連結訪問過後hover樣式就不出現了 被點選訪問過的超連結樣式不在具有hover和active瞭解決方法是改變CSS屬性的排列順序: L-V-H-A : a:link {} a:visited {} a:hover {} a:active {} * 怪異模式問題:漏寫DTD宣告,Firefox仍然會按照標準模式來解析網頁,但在IE中會觸發怪異模式。為避免怪異模式給我們帶來不必要的麻煩,最好養成書寫DTD宣告的好習慣。現在可以使用[html5]()推薦的寫法:`
`* 上下margin重合問題 ie和ff都存在,相鄰的兩個div的margin-left和margin-right不會重合,但是margin-top和margin-bottom卻會發生重合。 解決方法,養成良好的程式碼編寫習慣,同時採用margin-top或者同時採用margin-bottom。 * ie6對png圖片格式支援不好(引用一段指令碼處理)
常用的自適應解決方案
cookie,localStorage,sessionStorage 差異及使用場景
釋出 - 訂閱模式
ABC 收藏了某店鋪,店鋪更新商品時,ABC 就會收到通知。ABC 就是訂閱者,店鋪就是釋出者
多行文字垂直居中
父級高度不固定,即內容撐開父級時:為父級新增 padding 即可
父級高度固定(IE8 及以上有效):
1.父級新增:display:table;
2.子集新增:display:table-cell; vertical-align:middle
// css div { height:500px; width:300px; border:1px solid red; font-size: 30px; display: table; } p { display: table-cell; vertical-align: middle; } // html
啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦
未知大小圖片水平垂直居中
標籤外套一層
標籤
a{display:inline-block; width:1.2em; font-size:128px; text-align:center; vertical-align:middle;}img{vertical-align:middle;}
溢位顯示省略號
white-space: nowrap; text-overflow: ellipsis; overflow: hidden;
偽類 / 偽元素
偽類:
屬性 描述 CSS 向被啟用的元素新增樣式。 1 :focus 向擁有鍵盤輸入焦點的元素新增樣式。 2 當滑鼠懸浮在元素上方時,向元素新增樣式。 1 向未被訪問的連結新增樣式。 1 向已被訪問的連結新增樣式。 1 向元素的第一個子元素新增樣式。 2 向帶有指定 lang 屬性的元素新增樣式。 2 偽元素:
屬性 描述 CSS 向文字的第一個字母新增特殊樣式。 1 向文字的首行新增特殊樣式。 1 在元素之前新增內容。 2 在元素之後新增內容。 2
去掉 ul 前面的點
list-style:none
引用的阿里向量圖為什麼能改顏色
-
透過偽元素新增的
content
內容,屬於文字向量圖是偽元素的 content
BOM
BOM & DOM
關於 Vue 雙向繫結 和 虛擬DOM
-
例項化 MVVM 的過程中做了以下三件事:
1. 傳入一個 options 配置物件,類似這種,MVVM 的引數就是:var vm = new MVVM({ el: '#mvvm-app', data: { someStr: 'hello ', className: 'btn', htmlStr: 'red', child: { someStr: 'World !' } }, computed: { getHelloWord: function() { return this.someStr + this.child.someStr; } }, methods: { clickBtn: function(e) { var randomStrArr = ['childOne', 'childTwo', 'childThree']; this.child.someStr = randomStrArr[parseInt(Math.random() * 3)]; } } });
2. 例項化 Observer ,用於重寫 options.data 所有屬性的訪問器屬性,即 get 和 set 方法,重寫的目的是:
a. 透過重寫的get
實現:哪裡讀取資料,就把哪裡當做一個Watcher
,並將它存到dep.subs
中
b. 透過重寫的set
實現:修改data
資料時呼叫notice()
通知所有觀察者進行更新update()
3. 例項化 Compile , 用於編譯 options.el ,效果是:
a. 找出options.el
中引用到options.data
的部分,每找到一處就例項化一個觀察者Watcher
,而Watcher
本身定義有一個update()
方法
b. 初始化渲染,初始化時會讀取options.data
的資料用於渲染檢視,也就將所有Watcher
存入了dep.subs
虛擬DOM
將#mvvm-app
內的節點存為一個 文件片段,透過判斷模板{{}}
和各種v-
指令,將data
資訊寫到 文件片段 上,最後將 文件片段 一次插入#mvvm-app
中
幾個常用的正則
手機號:以 1 開頭,第二位是 3~8 中的一個,之後是 9 個 0~9 結尾
/^1[34578][0-9]{9}$/
日期匹配:前四位是數字,接著是
/
和-
中的一個,然後兩個數字,接著是/
和-
中的一個,然後兩個數字結尾
/^d{4}[/-]d{2}[/-]d{2}$/// 1983-12-27// 1983/12/16
郵箱:第一位是數字字母下劃線 + 數字字母下劃線橫線任意個 + @ + 數字字母至少一個 + (點 + 至少一個字母)至少一組結尾
/^[a-zA-Z0-9_][a-zA-Z0-9_-]*@[a-zA-Z0-9]+(.[a-zA-Z]+)+$/
練習:匹配
aabc222babc222bbabc
中的字母部分
/((a)|(b{1,2}))abc/g
Vue 中 data 為什麼使用 return
不使用 return 包裹的資料會在專案的全域性可見,會造成變數汙染
使用return 包裹後資料中變數只在當前元件中生效,不會影響其他元件。
Vue 中使用 data 中的一個陣列屬性渲染頁面,修改陣列屬性時,頁面是否響應
oninput / onchange
oninput:輸入框內容變了就觸發
onchange:輸入框內容變化並失去焦點時觸發
Vue 元件通訊
父 子:
1.prop
2.子元件呼叫 this.$parent
3.provide / inject父呼叫子方法
1.ref
link 和 @import
link 屬於 html 標籤,而 @import 是 css 提供的。
頁面被載入時,link會同時被載入,而 @import 引用的 css 會等到頁面載入結束後載入。
link 是 html 標籤,因此沒有相容性,而 @import 只有 IE5 以上才能識別。
link 方式樣式的權重高於 @import
SCSS
-
列表不同顏色
1.$
定義變數
2.@each ... in ...
列表迴圈
3.index(list,item)
內建方法,返回下標
4.#{}
插值
5.nth(list,idx)
內建方法,返回值效果
// html
這是第 1 條資訊這是第 2 條資訊這是第 4 條資訊這是第 5 條資訊// scss$color-list: #f5a623 #d0021b #4a90e2 #417505 #9012fe #b1bdca #4a459e;$color-name-list: orange red blue green blueviolet gray purple; @each $color in $color-name-list{ $i: index($color-name-list,$color); .a-#{$color}{ color:nth($color-list,$i) } }
瀏覽器相容
不同瀏覽器內外邊距不同
ie9
以下不支援HTML5
標籤和媒體查詢:使用html5shiv.js
和respone.js
部分瀏覽器
標籤之間有間隔:給
浮動
ie9
以下不支援opacity:filter:alpha(opacity=50)
蘋果瀏覽器不支援
cursor:hand
。統一用cursor:pointer
為不同瀏覽器的
CSS
字首:profixfree.js
ie8
:不支援placeholder
,用onfocus
和onblur
模擬,並且需要手動新增value
;或者用placeholder.js
-
ie8
:不支援裡面有
、
等元素的跳轉。
ie8
圓角:在css
中引入behavior:PIE.htc
flexible.js
750
的設計稿,flexible.js
將其分為100
份,每10
份為1rem
,因此1rem = 750 / 10 = 75px
750
的設計稿上有個寬195
的圖片,我們需要寫的rem
值為195 / 75 = 2.6 rem
判斷裝置
window.navigator.userAgent
// chrome"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36"// firefox"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0"// IE8"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)"// IE7"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)"// iPhone 5/SE 320*568"Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1"// iPhone 6/7/8 375*667"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"// Galaxy S5 360*640"Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Mobile Safari/537.36"
MVVM
作者:_我亦飄零
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2310/viewspace-2803449/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 前端知識點(持續更新)前端
- 前端面試知識點錦集前端面試
- 前端面試知識點目錄整理前端面試
- 前端知識點總結—面試專用前端面試
- 史上前端面試最全知識點前端面試
- 【ASIC設計】FPGA小知識拾遺(不斷更新...)FPGA
- 面試知識點面試
- 前端知識點前端
- java基礎:面試題【不斷更新】Java面試題
- html前端知識點HTML前端
- 前端小知識點前端
- 前端面試常見的知識點(四處搜刮)?前端面試
- 大前端常見面試題:HTML常考知識點前端面試題HTML
- 前端面試知識點(五)--- BFC的建立和作用前端面試
- 前端知識點總結——JS高階(持續更新中)前端JS
- php物件導向知識點PHP物件
- JVM面試知識點梳理JVM面試
- jQuery面試知識點整理jQuery面試
- android 面試知識點Android面試
- 面試必知的web知識點面試Web
- 前端知識點參考前端
- 前端面試中容易讓你忽略的知識點(一)前端面試
- SDWebImage面試常問點知識點Web面試
- 自己總結的部分面試題,不斷更新面試題
- 校招前端面試知識大全前端面試
- 前端跨域知識簡介前端跨域
- [前端經典面試篇] 中高階面試知識點 中大廠必問 (更新至四月第六版)前端面試
- CSS知識點面試總結CSS面試
- java面試知識點總結Java面試
- Flutter 面試知識點集錦Flutter面試
- 面試需要掌握的知識點面試
- Java 面試知識點總結Java面試
- Redis 面試必備知識點Redis面試
- css&html面試知識點CSSHTML面試
- Kafka面試知識點深度剖析Kafka面試
- React Native面試知識點React Native面試
- Java 基礎面試知識點Java面試
- web前端知識點(webpack篇)Web前端