前端js經典面試題目

/**
 * 用js實現一個類P 包含成員變量a,成員變量b成員函數sum sum輸出a與b的和,a,b默認值都爲0.實現一個類M,M繼承自P,在P的基礎上增加成員變量c成員變量函數sum變成a,b,c的和
 */
function P(a,b){
    this.a = a || 0;
    this.b = b || 0;
}
P.prototype.sum = function(){
    return this.a + this.b;
};

function M(a,b,c){
    P.call(this,a,b);
    this.c = c || 0;
}

M.prototype = new P();
M.prototype.constructor = M;

M.prototype.sum = function(){
    return this.a + this.b + this.c;
};

var p = new P(1,2);
var m = new M(1,2,3);
console.log("p.sum()=",p.sum());
console.log("m.sum()=",m.sum());

/**
 * 寫出三個不同的this使用場景
 */

// 0. 構造器函數內的this:
//如果函數創建的目的是使用new來調用,併產生一個對象,那麼此函數被稱爲 構造器函數。
// var Niu = function (string) {
//
//     this.name = string;
// };
// 上述的Niu即爲一個構造器函數,其內部的this會自動綁定到new所創建的新對象上面。
//
// 1. 對象成員方法內的this:
// 對象的成員方法中的this是對象本身,此時跟其它語言是一致的,但是也有差異,javascript中this到對象的綁定發生在函數調用的時候。
//
// var myObj = {
//
//     value: 0,
//
//     increment: function (inc) {
//
//         this.value += typeof inc === 'number' ? inc : 1;
//
//     }
//
// };
//
// myObj.increment();    //1
//
// myObj.increment(2);   //3

// 2. 普通函數 與 閉包內的this:
//
//     2.1 以普通方式定義的函數中的this:會被自動綁定到全局對象。
// var value = 232;
//
// function toStr()
//
// {
//
//     console.log("%d", this.value);  //232
//
// }
//
//
// 2.2 對象方法中閉包函數的this:
//
//     由2.1可知,在以普通方式定義的函數中的this會被自動綁定到全局對象上,大家應該可以看出閉包函數定義也與普通方式無異,因此他也會被綁定到全局對象上。
//
// value = 10;<br>var closureThis = {
//     value: 0,
//     acc: function ()
//     {
//         var helper = function ()
//         {
//             this.value += 2;
//             console.log("this.value : %d", this.value);
//         }
//         helper();
//     }
// };
//
// closureThis.acc();   //12
// closureThis.acc();   //14
//
// var closureThat = {
//     value: 0,
//     acc: function ()
//     {
//         that = this;
//         var helper = function ()
//         {
//             that.value += 2;
//             console.log("that.value : %d", that.value);
//         }
//         helper();
//     }
// };
//
// closureThat.acc(); // 2
// closureThat.acc(); // 4
// 從上述輸出值可以看出,上述描述的正確性。
//
// 3. Apply函數的參數this:
//
// appy方法允許我們選擇一個this值作爲第一個參數傳遞,第二個參數是一個數組,表明可以傳遞多個參數。


//【場景1】全局環境中的this指向全局對象
// this.a = 10;
// alert(a);//10
// b = 20;
// alert(this.b);//20
// var c = 30;
// alert(this.c);//30
// 【場景2】對象內部函數的this指向調用函數的當前對象
// var a = 10;
// var bar = {
//     a: 20,
//     test: function(){
//         alert(this.a);
//     }
// }
// bar.test();//20
// 【場景3】全局環境函數的this指向全局對象
// var a = 10;
// function foo(){
//     alert(this.a);
// }
// foo();//10
// 【場景4】匿名函數中的this指向全局對象
// var a = 10;
// var foo = {
//     a: 20,
//     fn: (function(){
//         alert(this.a);
//     })()
// }
// foo.fn//10
// 【場景5】setInterval和setTimeout定時器中的this指向全局對象
// var a = 10;
// var oTimer1 = setInterval(function(){
//     var a = 20;
//     alert(this.a);//10
//     clearInterval(oTimer1);
// },100);
// 【場景6】eval中的this指向調用上下文中的this
// (function(){
//     eval("alert(this)");//[object Window]
// })();
// function Foo(){
//     this.bar = function(){
//         eval("alert(this)");//[object Object]
//     }
// }
// var foo = new Foo();
// foo.bar();
// 【場景7】構造函數中的this指向構造出的新對象
// function Person(name,age){
//     this.name = name;
//     this.age = age;
//     this.sayName = function(){
//         alert(this.name);
//     }
// }
// var p1 = new Person('lily','20');
// p1.sayName();//'lily'
// 【場景8】new Function中的this指向全局對象
// (function(){
//     var f = new Function("alert(this)");
//     f();//[object Window]
// })();
// function Foo(){
//     this.bar = function(){
//         var f = new Function("alert(this)");
//         f();//[object Window]
//     }
// }
// var foo = new Foo();
// foo.bar();
// 【場景9】apply和call中的this指向參數中的對象
// var a = 10;
// var foo = {
//     a: 20,
//     fn: function(){
//         alert(this.a);
//     }
// };
// var bar ={
//     a: 30
// }
// foo.fn.apply();//10(若參數爲空,默認指向全局對象)
// foo.fn.apply(foo);//20
// foo.fn.apply(bar);//30
// 【複合場景1】
// var someone = {
//     name: "Bob",
//     showName: function(){
//         alert(this.name);
//     }
// };
// var other = {
//     name: "Tom",
//     showName: someone.showName
// }
// other.showName();  //Tom
//
// //以上函數相當於
//
// var other = {
//     name: "Tom",
//     showName: function(){
//         alert(this.name);
//     }
// }
// other.showName();  //Tom
// 【複合場景2】
// var name = 2;
// var a = {
//     name: 3,
//     fn: (function(){
//         alert(this.name);
//     })(),
//     fn1:function(){
//         alert(this.name);
//     }
// }
// a.fn;//2[匿名函數中的this指向全局對象]
// a.fn1();//3[對象內部函數的this指向調用函數的當前對象]
//
// 【複合場景3】
// var name = "Bob";
// var nameObj ={
//     name : "Tom",
//     showName : function(){
//         alert(this.name);
//     },
//     waitShowName : function(){
//         var that = this;
//         setTimeout(function(){
//             that.showName();
//         }, 1000);
//     }
// };
// nameObj.waitShowName();//"Tom"[that=this改變this的指向,使this從指向全局變量變化到指向nameObj]
//
// var name = "Bob";
// var nameObj ={
//     name : "Tom",
//     showName : function(){
//         alert(this.name);
//     },
//     waitShowName : function(){
//         var that = this;//that指向nameObj
//         setTimeout(function(){
//             (function(){
//                 alert(this.name);
//             })();
//         }, 1000);
//     }
// };
// nameObj.waitShowName();// 'Bob'[形成匿名函數,this指向全局變量]


/**
 * 寫出下面這段代碼的執行結果
 */
for(var i = 0 ; i < 3 ; i ++){
    setTimeout(function(){
        console.log(i);
    },0);
}

/**
 * 執行結果:
 * 3
 * 3
 * 3
 * 原因:js是單程的,會先執行for然後有空閒的時候再執行setTimeout,雖然setTimeout的時間延時爲0,還是會緩存等待for循環執行結束之後等有空閒的時候再執行
 */

/**
 * 說出以下函數的作用,並填寫空格內容
 */

//define
(function(window){
    function fn(str){
        this.str = str;
    }
    fn.prototype.format = function(){
        var arg = ____;
        return this.str.replace(____,function(a,b){
            return arg[b] || "";
        });
    };
    window.fn = fn;
})(window);

//use
(function(){
    var t = new fn('<p><a href = "{0}">{1}</a><span>{2}</span></p>');
    console.log(t.format('http://www.baidu.com','BaiDuSecurites','Welcome'));
})();

/**
 * 將字符串中的特定字符用函數的參數來替換
 */

//define 這裏是一個私有作用域,爲了讓外面的函數可以訪問到fn函數,傳入了window對象,並且最終將定義的函數賦值到了window中的fn上了,所以外面可以訪問到
(function(window){
    function fn(str){
        this.str=str;
    }
    fn.prototype.format=function(){
        var arg=arguments;
        return this.str.replace(/\{(\d+)\}/ig,function(a,b){
            // console.log(a);
            // console.log(arg);
            // console.log(b);
            console.log(arg[b]);
            return arg[b]||'';
        });
    }
    window.fn=fn;
})(window);

//use
(function(){
    var t=new fn('<p><a href="{0}">{1}</a><span>{2}</span></p>');
    console.log(t.format('http://www.alibaba.com','Alibaba','Welcome'));
})();

/**
 * 用js實現一個Promise,要求支持resolve,reject,done,fail,then,always.
 */

// state: 當前執行狀態,有pending、resolved、rejected3種取值
//
// done: 向doneList中添加一個成功回調函數
//
// fail: 向failList中添加一個失敗回調函數
//
// then: 分別向doneList和failList中添加回調函數
//
// always: 添加一個無論成功還是失敗都會調用的回調函數
//
// resolve: 將狀態更改爲resolved,並觸發綁定的所有成功的回調函數
//
// reject: 將狀態更改爲rejected,並觸發綁定的所有失敗的回調函數
//
// when: 參數是多個異步或者延遲函數,返回值是一個Promise兌現,當所有函數都執行成功的時候執行該對象的resolve方法,反之執行該對象的reject方法
// 下面是我的具體實現過程:

var Promise = function() {
    this.doneList = [];
    this.failList = [];
    this.state = 'pending';
};

Promise.prototype = {
    constructor: 'Promise',
    resolve: function() {
        this.state = 'resolved';
        var list = this.doneList;
        for(var i = 0, len = list.length; i < len; i++) {
            list[0].call(this);
            list.shift();
        }
    },
    reject: function() {
        this.state = 'rejected';
        var list = this.failList;
        for(var i = 0, len = list.length; i < len; i++){
            list[0].call(this);
            list.shift();
        }
    },
    done: function(func) {
        if(typeof func === 'function') {
            this.doneList.push(func);
        }
        return this;
    },
    fail: function(func) {
        if(typeof func === 'function') {
            this.failList.push(func);
        }
        return this;
    },
    then: function(doneFn, failFn) {
        this.done(doneFn).fail(failFn);
        return this;
    },
    always: function(fn) {
        this.done(fn).fail(fn);
        return this;
    }
};

function when() {
    var p = new Promise();
    var success = true;
    var len = arguments.length;
    for(var i = 0; i < len; i++) {
        if(!(arguments[i] instanceof Promise)) {
            return false;
        }
        else {
            arguments[i].always(function() {
                if(this.state != 'resolved'){
                    success = false;
                }
                len--;
                if(len == 0) {
                    success ? p.resolve() : p.reject();
                }
            });
        }
    }
    return p;
}
// Improve
// 目前只是實現了Promise的基礎功能,但仍然還有無法處理的情況,例如要實現3個或3個以上的異步請求的串行,目前我的Promise沒有辦法支持new Promise(A).then(B).then(C)這樣的形式,jQuery在1.7的版本中爲Deferred(Promise)對象實現了pipe函數,可以通過這個函數實現上述功能,代碼爲$.Deferred(A).pipe(B).then(C),我嘗試去讀了jQuery這部分的代碼,但是沒能讀懂,希望有大神能夠給一些實現思路




/**
 * 兩個順序排列的數組A和B,求B數組是否爲A數組的子集。(數組內可能有重複數字)
 */

var A = [1,2,2,2,2,3,5,5,5,6,8,9,9,9];
var B = [1,2,3];
/**
 * A,B,分別是兩個順序排列的數組,判斷B是否爲A的子集
 * @param _A
 * @param _B
 * @returns {boolean}
 */

function isASon(_A,_B){
    var flag = false;
    if(_A instanceof Array && _B instanceof Array){
        var i = 0,j = 0 ;
        while(i < _B.length){
            flag = false;
            for( ; j < _A.length ; j ++){
                if(_B[i] === _A[j] ){
                    flag = true;
                    break;
                }
            }
            if(flag){
                i ++;
            }else{
                return false;
            }
        }
        if(flag){
            return true ;
        }else{
            return false;
        }
    }
}

    isASon(A,B);


希望我的入坑經驗對你有所幫助,願聖光與你同在

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