【面試向】極簡前端知識點(不斷更新)

amadan發表於2021-09-09
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() - delay 
    console.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]'
  • 判斷 NaNisNaN(),或者 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 得知 xPerson,而工廠模式則無法知道 xPerson

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 ,並且不同例項的 arrsay 並不是一個玩意

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 後,floatclearvertical-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 分別指向 argumentsfoofoo


    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.jsrespone.js

    • 部分瀏覽器 【面試向】極簡前端知識點(不斷更新) 標籤之間有間隔:給 【面試向】極簡前端知識點(不斷更新) 浮動

    • ie9 以下不支援 opacity:filter:alpha(opacity=50)

    • 蘋果瀏覽器不支援 cursor:hand。統一用 cursor:pointer

    • 為不同瀏覽器的 CSS 字首:profixfree.js

    • ie8:不支援 placeholder,用 onfocusonblur 模擬,並且需要手動新增 value;或者用 placeholder.js

    • ie8:不支援 裡面有 等元素的跳轉。

    • ie8 圓角:在 css 中引入 behavior:PIE.htc


    flexible.js

    • 實際應用:https://www.cnblogs.com/screw/p/5159506.html

    • 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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章