前端題2

 

23. 監聽輸入:

    1. oninput  > onchange:  onchange在離焦事件是觸發。不如input靈敏 ( IE9+ )

    2. 中文輸入時(即非直接輸入),input獲取的值不正確,需加判斷。( IE9+ )

        compositionstart:當瀏覽器有非直接的文字輸入時, compositionstart事件會以同步模式觸發.

        compositionEnd:    當瀏覽器是直接的文字輸入時, compositionend會以同步模式觸發.

var cpLock = false;
input.addEventListener('compositionstart', function(){
    cpLock = true;
})
input.addEventListener('compositionend', function(){
    cpLock = false;
})
input.addEventListener('input', function(){
    if(!cpLock)console.log(this.value);
});

    3. 需要兼容IE9一下的,只能使用keyPress,keyDown等事件,判斷keyCode

    (參考做法:http://jyren-rachel.iteye.com/blog/1886275)

 

24. 遞歸中的性能:

        遞歸是處遍歷外最常用的循環方法。鑑於其性能問題,一般能用while,for等循環的儘量不用遞歸。 若必須用遞歸方法,一般把遞歸中的執行代碼放入setTimeout方法中,以避免棧溢出(setTimeout總是在下一次的tick中執行)。

        setInterval的不靠譜:當每次執行的時間小於循環時間時,不會出現異常;而當代碼執行時間較長,超出循環時間時,下一次的循環將被延後,這樣每次的循環間隔將不統一,且任務會堆積在隊列中。

更詳細的介紹https://www.cnblogs.com/simonbaker/p/5707270.html

25. es6屬性:

    1. let , const

        let : a. 不存在變量提升, 必須先聲明 後使用。(會報錯 is not defined ;var 中則不報錯,返回值爲 undefined)

               b. 存在塊作用域內,同域內不可重複聲明

               c. 暫時性死區:一旦在作用域內聲明瞭次變量,若提前訪問會報錯,(即使外域也聲明瞭同名變量)

        const : 與 let 特點相同,聲明時必須賦值,且不能更改賦值,若是對象保存的是對象的地址。

 

    2. 結構賦值 : 等號右邊的值會賦予左邊的變量。        

   

    3. 模板字符串: ‘字符串’,按照字符串處理拼接。

        a. 反引號爲特殊字符,使用的話需加 \ 轉義。

        b. 花括號內可以進行 js 運算

        c. 空格、縮進都會被保留

         `${1}+${2}`  //  '1+2'

    4.   rest參數  , 擴展運算符

        rest :  (. . .a)  作爲參數或者等號左邊變量 必須爲最後一個參數

        擴展運算符: 相當於rest的逆運算, 展開一個數組或者對象

    5.class 類,super方法:(阮一峯:https://m.imooc.com/article/20618

        注:react中一般寫法: super ( props );這樣寫的原因是 在constructor 中可以使用 this.props,  props是實例化時傳入的參數。

        (子類纔會有super方法,父類是沒有的);在子類的構造函數中,只有調用super之後,才能使用this關鍵字,否則會報錯,這是因爲子類沒有自己的this對象,而是繼承父類的this對象,然後對其進行加工,如果不調用super方法,子類就得不到this對象;

        如果子類沒有定義constructor方法,這個方法會默認添加,也就是說,不管有沒有顯式定義,任何一個子類都有constructor方法。

        通過super調用父類的方法時,super會綁定子類的this。

        super當作函數調用時,代表父類的構造函數;super作爲對象時,在普通方法中,指向父類的原型對象,在靜態方法中,指向父類

 

26. http1.0 和 http2.0:

    http2增加了:

  • 多路複用
  • 壓縮頭信息
  • 請求劃分優先級
  • 支持服務器端主動推送 
  • 只支持https

27.  use strict 嚴格模式:(參考文章:https://blog.csdn.net/weixin_40387601/article/details/80514358)

        js 以更嚴謹的方式運行。

 

28. 小程序實現vue類型的數據監聽:Object.defineProperty方法

    

    /**
     * 設置監聽器
     */
    setWatcher(page) {
        let data = page.data;
        let watch = page.watch;
        Object.keys(watch).forEach(v => {
            let key = v.split('.'); // 將watch中的屬性以'.'切分成數組
            let nowData = data; // 將data賦值給nowData
            for (let i = 0; i < key.length - 1; i++) { // 遍歷key數組的元素,除了最後一個!
                nowData = nowData[key[i]]; // 將nowData指向它的key屬性對象
            }
            let lastKey = key[key.length - 1];
            // 假設key==='my.name',此時nowData===data['my']===data.my,lastKey==='name'
            let watchFun = watch[v].handler || watch[v]; // 兼容帶handler和不帶handler的兩種寫法
            let deep = watch[v].deep; // 若未設置deep,則爲undefine
            this.observe(nowData, lastKey, watchFun, deep, page); // 監聽nowData對象的lastKey
        })
    },
    /**
     * 監聽屬性 並執行監聽函數
     */
    observe(obj, key, watchFun, deep, page) {
        var val = obj[key];
        // 判斷deep是true 且 val不能爲空 且 typeof val==='object'(數組內數值變化也需要深度監聽)
        if (deep && val != null && typeof val === 'object') { 
            Object.keys(val).forEach(childKey=>{ // 遍歷val對象下的每一個key
                this.observe(val,childKey,watchFun,deep,page); // 遞歸調用監聽函數
            })
        }
        var that = this;
        Object.defineProperty(obj, key, {
            configurable: true,
            enumerable: true,
            set: function(value) {
                // 用page對象調用,改變函數內this指向,以便this.data訪問data內的屬性值
                watchFun.call(page,value,val); // value是新值,val是舊值
                val = value;
                if(deep){ // 若是深度監聽,重新監聽該對象,以便監聽其屬性。
                    that.observe(obj, key, watchFun, deep, page); 
                }
            },
            get: function() {
                return val;
            }
        })
    }


page中使用:

//index.js
 
Page({
    data: {
        my: {
            name: 'xuyang',
            age: 21,
            hobby: ['girls', 'games']
        },
        nameInfo:{}
    },
    onLoad() {
        getApp().setWatcher(this);
        this.data.my.hobby[0] = 'study';
        this.setData({
            nameInfo:{name:'haha',sex:'boy'}
        })
        console.log(this.data)
    },
    watch: {
        my:{
            handler(newValue) {
                console.log(newValue);
            },
            deep:true
        }
    }
})

        (轉載鏈接:https://blog.csdn.net/xuyangxinlei/article/details/81408200)

29. CSS 3  + HTML 5  (postcss-loader只是給 css 添加前綴,通gulp中的autoprefixer, 謹慎使用新屬性)

    1.選擇器:

        屬性:[att=val] 指定特定名字的元素

              [att*=val] 匹配val*的元素,

              [att^=val] 匹配val開頭的元素,比如id爲val1、val432432都可以。

              [att$=val] 匹配val結尾的元素,比如id爲1213val、fdajlval等等。

        順序:first-child:選擇第一個子元素

              last-child:選擇最後一個子元素

              nth-child:選擇第n個子元素,這個還可以根據奇偶來制定,

                   nth-last-child:選擇倒數第n個子元素

              only-child:單個子元素時,指定樣式

        狀態: hover , active ,checked , selection, focus , enabled , disabled , read-only

    2. 效果: border-radius , box-shadow  , box-sizing , background屬性 , linear-gradient , radial-gradient

    3.動畫:

        1.關鍵幀動畫:animation: name  duration timing-function delay count;    @keyframes

        2.2D效果屬性: tranform :     translate  、rotate、scale ;    transition   

    4. html5 :

        1.語義化標籤: nav ,head ,footer , aside,article,section;

        2. 拖拽: drag  , drop 

        3. vedio 、audio、canvas

        4.input 新類型: time , date , email , url ,  search  ,calendar ,  datetime, week , month , color , tel ,number ,

        5. websocket , localstorage 

 

28.閉包:定義 , 效果:可以獲去操作一個函數中的局部變量。缺點:消耗內存,一直保持父函數的引用。 優點: 對局部變量保護作用,利於函數的 封裝。

 

29. CMD,AMD比較:

    AMD(異步模塊定義):requirejs  : 提前下載,提前執行

    CMD(通用模塊定義):seajs       :提前下載,延遲執行    

    RequireJS 和 SeaJS 都是很不錯的模塊加載器,兩者區別如下:

    1. 兩者定位有差異。RequireJS 想成爲瀏覽器端的模塊加載器,同時也想成爲 Rhino / Node 等環境的模塊加載器。SeaJS 則專注於 Web 瀏覽器端,同時通過 Node 擴展的方式可以很方便跑在 Node 服務器端

    2. 兩者遵循的標準有差異。RequireJS 遵循的是 AMD(異步模塊定義)規範,SeaJS 遵循的是 CMD (通用模塊定義)規範。規範的不同,導致了兩者 API 的不同。SeaJS 更簡潔優雅,更貼近 CommonJS Modules/1.1 和 Node Modules 規範。

    3. 兩者社區理念有差異。RequireJS 在嘗試讓第三方類庫修改自身來支持 RequireJS,目前只有少數社區採納。SeaJS 不強推,而採用自主封裝的方式來“海納百川”,目前已有較成熟的封裝策略。

    4. 兩者代碼質量有差異。RequireJS 是沒有明顯的 bug,SeaJS 是明顯沒有 bug。

    5. 兩者對調試等的支持有差異。SeaJS 通過插件,可以實現 Fiddler 中自動映射的功能,還可以實現自動 combo 等功能,非常方便便捷。RequireJS 無這方面的支持。

    6. 兩者的插件機制有差異。RequireJS 採取的是在源碼中預留接口的形式,源碼中留有爲插件而寫的代碼。SeaJS 採取的插件機制則與 Node 的方式一致:開放自身,讓插件開發者可直接訪問或修改,從而非常靈活,可以實現各種類型的插件。.

    (來源文章:http://www.cnblogs.com/dojo-lzz/p/4707725.html

 

30. arguments對象:函數的參數對象

    特點:1. 不是數組,但是有數組的一些屬性,length,索引,變成數組的方法:[].slice.call(arguments)或Array.prototype.slice.call(arguments);

                   typeof arguments   // obeject ;            {}.tostring.call(arguments)   // [object Arguments]

              2. 實參中的值和arguments中的值保持一致。

              3. length的值不會自動改變,必須主動設置,但可以訪問

              4. 屬性callee:arguments.callee指向函數本身,可以用於遞歸中,優點是即使函數名稱改變,也不會報錯 ; arguments.callee.caller指向調用此函數的函數,若無爲null,

              5. 嚴格模式下,對arguments操作,只對arguments有效,對參數無效。

function test(a,b,c){
    console.log(c);
    arguments[2]=10;
    console.log(c);
    arguments[3]=10;
    console.log(arguments[3]);
    console.log(arguments.length);
    arguments.length=4;
    console.log(arguments.length);
}

test(1,2,3)
// 結果: 
//        3
//        10           特點2
//        10           特點3   
//         3   
//         4

test(1,2)
// 結果: 
//        undefined    特點2
//        10           特點3   
//        10   
//        2
//        4

 

31. 隊列,宏任務,微任務:參考:https://juejin.im/post/59e85eebf265da430d571f89

 

32. SEO及優化:

    1. TDK:title , description , keywords

    2. 標題標籤,img的alt屬性,語義化標籤,

    SPA的優化:單頁面應用對國內瀏覽器seo很不友好,國外瀏覽器不受影響。

                    a. 預渲染    b. ssr 服務端渲染,首屏採用服務端渲染。nuxt.js

                    vue : prerender-plugin  + vue-meta-info

 

33. sort方法:瀏覽器的實現方式不同:V8:<=22使用InsertionSort ,>22使用QuickSort排序。ff:歸併排序

//自定義sort方法:
Array.prototype.mySort = function (fn) {
    for (var i = this.length; i >0; i--) {
        for (var j =0; j < i; j++) {
            if (fn && typeof fn == 'function') {
                if(fn(this[j] ,this[j+1])>0){
                    [this[j], this[j+1]] = [this[j+1], this[j]];
                }
            } else {
                var a = String(this[j]),b=String(this[j+1]);
                if(charcode(a,b)>0){
                    var temp=this[j];
                    this[j] = this[j+1];
                    this[j+1] = temp;
                    // [this[j+1], this[j]] = [this[j], this[j+1]];
                }
            }
        }
    }
    function charcode(a,b){    
        if(a.charCodeAt(0)<b.charCodeAt(0)){
           return -1
        }else if(a.charCodeAt(0)>b.charCodeAt(0)){
            return 1
         }else{
            if(a.slice(1)===''){
                return -1
            }else if(b.slice(1)===''){
                return 1
            }else{
                return charcode(a.slice(1),b.slice(1))
            } 
        }
    }
    return this;
}

    

34. 構造函數:   

 //js中沒有類的概念(es6中也只是中語法糖),所以通過原型鏈實現繼承這種機制。

 //構造函數實際上就是普通函數,返回一個實例對象
  function Test(name,age){
      this.name=name;
      this.age=age;
  }; 

 //每個函數都有prototype屬性,一個對象,是所以實例對象共有的屬性方法,因爲都引用這個對象,new 的過程中會自動添加constructor屬性,構造函數本身。
   Test.prototype.constructor = Test;
   Test.prototype.fn=function(){};

 //一個實例的屬性分爲兩部分:自有屬性 + 公共屬性
   var  test = new Test(1,2);  // name , age ,  fn

 //通過 hasOwnProperty 判斷屬性是否是自有屬性
   test.hasOwnProperty('fn')   // false

 //通過 isPrototypeOf 判斷 實例 是否是構造函數的實例
   Test.prototype.isPrototypeOf(test) // true;
   

 

35原型鏈:

數據類型:undefined,null,Number,String,Boolean + Object 六大類型。

Number,String,Boolean, Object,Function等都是構造函數,typeof 值:‘function’
生成相應類型的數據可以直接定義,也可以通過構造函數生成(這種方式生成的返回值都是一個 object,function例外,返回的是function),

// 1.prototype:只有函數有此屬性,

// 2.__proto__:對象的此屬性指向構造函數的prototype, 函數的此屬性指向Function的prototype(所以的函數都是Function的實例),
     Obeject.__proto__ === Function.prototype   // true    typeof 爲function,此function較特殊,沒有prototype屬性,
     Object.__proto__.__proto__ ===Object.prototype  // true   擁有object的屬性
     

//constructor:指向構造函數本身,在34中,是在prototype中的默認一個屬性。因此所以的實例中也會有此方法,

sd

36.運算符優先級及轉換

var a = (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]] + ({}+[])[[~!+[]]*~+[]];  
     // sb  (--的優先級大於*;~改變正負值再減一;[]是空=>0;{}是[object Object])

 

 

sd

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章