javascript(面向對象,做用域,閉包,設計模式等)

javascript(面向對象,做用域,閉包,設計模式等)

  • 1. 經常使用js類定義的方法有哪些?

參考答案:主要有構造函數原型和對象建立兩種方法。原型法是通用老方法,對象建立是ES5推薦使用的方法.目前來看,原型法更廣泛.javascript

代碼演示
1) 構造函數方法定義類java

    function Person(){
        this.name = 'michaelqin';
    }
    Person.prototype.sayName = function(){
        alert(this.name);
    }

    var person = new Person();
    person.sayName();

2) 對象建立方法定義類設計模式

var Person = {
        name: 'michaelqin',
        sayName: function(){ alert(this.name); }
    };

    var person = Object.create(Person);
    person.sayName();
  • 2. js類繼承的方法有哪些

參考答案:原型鏈法,屬性複製法和構造器應用法. 另外,因爲每一個對象能夠是一個類,這些方法也能夠用於對象類的繼承.數組

代碼演示
1) 原型鏈法閉包

    function Animal() {
        this.name = 'animal';
    }
    Animal.prototype.sayName = function(){
        alert(this.name);
    };

    function Person() {}
    Person.prototype = Animal.prototype; // 人繼承自動物
    Person.prototype.constructor = 'Person'; // 更新構造函數爲人

2) 屬性複製法app

    function Animal() {
        this.name = 'animal';
    }
    Animal.prototype.sayName = function() {
        alert(this.name);
    };

    function Person() {}

    for(prop in Animal.prototype) {
        Person.prototype[prop] = Animal.prototype[prop];
    } // 複製動物的全部屬性到人量邊
    Person.prototype.constructor = 'Person'; // 更新構造函數爲人

3) 構造器應用法ide

    function Animal() {
        this.name = 'animal';
    }
    Animal.prototype.sayName = function() {
        alert(this.name);
    };

    function Person() {
        Animal.call(this); // apply, call, bind方法均可以.細微區別,後面會提到.
    }
  • 3. js類多重繼承的實現方法是怎麼樣的?

參考答案:就是類繼承裏邊的屬性複製法來實現.由於當全部父類的prototype屬性被複制後,子類天然擁有相似行爲和屬性.函數

  • 4. js裏的做用域是什麼樣子的?

參考答案:大多數語言裏邊都是塊做做用域,以{}進行限定,js裏邊不是.js裏邊叫函數做用域,就是一個變量在全函數裏有效.好比有個變量p1在函數最後一行定義,第一行也有效,可是值是undefined.this

代碼演示spa

    var globalVar = 'global var';

    function test() {
        alert(globalVar); // undefined, 由於globalVar在本函數內被重定義了,致使全局失效,這裏使用函數內的變量值,但是此時還沒定義
        var globalVar = 'overrided var'; // globalVar在本函數內被重定義
        alert(globalVar); // overrided var
    }
    alert(globalVar); // global var,使用全局變量
  • 5. js裏邊的this指的是什麼?

參考答案: this指的是對象自己,而不是構造函數.

代碼演示

    function Person() {
    }
    Person.prototype.sayName() { alert(this.name); }

    var person1 = new Person();
    person1.name = 'michaelqin';
    person1.sayName(); // michaelqin
  • 6. apply, call和bind有什麼區別?

參考答案:三者均可以把一個函數應用到其餘對象上,注意不是自身對象.apply,call是直接執行函數調用,bind是綁定,執行須要再次調用.apply和call的區別是apply接受數組做爲參數,而call是接受逗號分隔的無限多個參數列表,

代碼演示

    function Person() {
    }
    Person.prototype.sayName() { alert(this.name); }

    var obj = {name: 'michaelqin'}; // 注意這是一個普通對象,它不是Person的實例
    1) apply
    Person.prototype.sayName.apply(obj, [param1, param2, param3]);

    2) call
    Person.prototype.sayName.call(obj, param1, param2, param3);

    3) bind
    var sn = Person.prototype.sayName.bind(obj);    
    sn([param1, param2, param3]); // bind須要先綁定,再執行 
    sn(param1, param2, param3); // bind須要先綁定,再執行
  • 7. caller, callee和arguments分別是什麼?

參考答案: caller,callee之間的關係就像是employer和employee之間的關係,就是調用與被調用的關係,兩者返回的都是函數對象引用.arguments是函數的全部參數列表,它是一個類數組的變量.

代碼演示

    function parent(param1, param2, param3) {
        child(param1, param2, param3);
    }

    function child() {
        console.log(arguments); // { '0': 'mqin1', '1': 'mqin2', '2': 'mqin3' }
        console.log(arguments.callee); // [Function: child]
        console.log(child.caller); // [Function: parent]
    }

    parent('mqin1', 'mqin2', 'mqin3');
  • 8. 什麼是閉包,閉包有哪些用處?

參考答案: 閉包這個術語,不管中文翻譯仍是英文解釋都太2B了,我必須罵人,由於它什麼其實都不是.非要講它是什麼的話,兩個字函數,更多字嵌套函數的父子自我引用關係.全部函數都是閉包.通俗的說,閉包就是做用域範圍,由於js是函數做用域,因此函數就是閉包.全局函數的做用域範圍就是全局,因此無須討論.更多的應用實際上是在內嵌函數,這就會涉及到內嵌做用域,或者叫做用域鏈.說到內嵌,其實就是父子引用關係(父函數包含子函數,子函數由於函數做用域又引用父函數,這它媽不是死結嗎?因此叫閉包),這就會帶來另一個問題,何時引用結束?若是不結束,就會一直佔用內存,引發內存泄漏.好吧,不用的時候就引用設爲空,死結就解開了.

  • 9. defineProperty, hasOwnProperty, propertyIsEnumerable都是作什麼用的?

參考答案:Object.defineProperty(obj, prop, descriptor)用來給對象定義屬性,有value,writable,configurable,enumerable,set/get等.hasOwnProerty用於檢查某一屬性是否是存在於對象自己,繼承來的父親的屬性不算.propertyIsEnumerable用來檢測某一屬性是否可遍歷,也就是能不能用for..in循環來取到.

  • 10. js經常使用設計模式的實現思路,單例,工廠,代理,裝飾,觀察者模式等

參考答案:

    1) 單例: 任意對象都是單例,無須特別處理
    var obj = {name: 'michaelqin', age: 30};

    2) 工廠: 就是一樣形式參數返回不一樣的實例
    function Person() { this.name = 'Person1'; }
    function Animal() { this.name = 'Animal1'; }

    function Factory() {}
    Factory.prototype.getInstance = function(className) {
        return eval('new ' + className + '()');
    }

    var factory = new Factory();
    var obj1 = factory.getInstance('Person');
    var obj2 = factory.getInstance('Animal');
    console.log(obj1.name); // Person1
    console.log(obj2.name); // Animal1

    3) 代理: 就是新建個類調用老類的接口,包一下
    function Person() { }
    Person.prototype.sayName = function() { console.log('michaelqin'); }
    Person.prototype.sayAge = function() { console.log(30); }

    function PersonProxy() { 
        this.person = new Person();
        var that = this;
        this.callMethod = function(functionName) {
            console.log('before proxy:', functionName);
            that.person[functionName](); // 代理
            console.log('after proxy:', functionName);
        }
    }

    var pp = new PersonProxy();
    pp.callMethod('sayName'); // 代理調用Person的方法sayName()
    pp.callMethod('sayAge'); // 代理調用Person的方法sayAge() 

    4) 觀察者: 就是事件模式,好比按鈕的onclick這樣的應用.
    function Publisher() {
        this.listeners = [];
    }
    Publisher.prototype = {
        'addListener': function(listener) {
            this.listeners.push(listener);
        },

        'removeListener': function(listener) {
            delete this.listeners[listener];
        },

        'notify': function(obj) {
            for(var i = 0; i < this.listeners.length; i++) {
                var listener = this.listeners[i];
                if (typeof listener !== 'undefined') {
                    listener.process(obj);
                }
            }
        }
    }; // 發佈者

    function Subscriber() {

    }
    Subscriber.prototype = {
        'process': function(obj) {
            console.log(obj);
        }
    }; // 訂閱者


    var publisher = new Publisher();
    publisher.addListener(new Subscriber());
    publisher.addListener(new Subscriber());
    publisher.notify({name: 'michaelqin', ageo: 30}); // 發佈一個對象到全部訂閱者
    publisher.notify('2 subscribers will both perform process'); // 發佈一個字符串到全部訂閱者
  • 11. 列舉數組相關的經常使用方法

參考答案: push/pop, shift/unshift, split/join, slice/splice/concat, sort/reverse, map/reduce, forEach, filter

  • 12. 列舉字符串相關的經常使用方法

參考答案: indexOf/lastIndexOf/charAt, split/match/test, slice/substring/substr, toLowerCase/toUpperCase

javascript高級話題(面向對象,做用域,閉包,設計模式等)

  • 1. 經常使用js類定義的方法有哪些?

參考答案:主要有構造函數原型和對象建立兩種方法。原型法是通用老方法,對象建立是ES5推薦使用的方法.目前來看,原型法更廣泛.

代碼演示
1) 構造函數方法定義類

    function Person(){
        this.name = 'michaelqin';
    }
    Person.prototype.sayName = function(){
        alert(this.name);
    }

    var person = new Person();
    person.sayName();

2) 對象建立方法定義類

var Person = {
        name: 'michaelqin',
        sayName: function(){ alert(this.name); }
    };

    var person = Object.create(Person);
    person.sayName();
  • 2. js類繼承的方法有哪些

參考答案:原型鏈法,屬性複製法和構造器應用法. 另外,因爲每一個對象能夠是一個類,這些方法也能夠用於對象類的繼承.

代碼演示
1) 原型鏈法

    function Animal() {
        this.name = 'animal';
    }
    Animal.prototype.sayName = function(){
        alert(this.name);
    };

    function Person() {}
    Person.prototype = Animal.prototype; // 人繼承自動物
    Person.prototype.constructor = 'Person'; // 更新構造函數爲人

2) 屬性複製法

    function Animal() {
        this.name = 'animal';
    }
    Animal.prototype.sayName = function() {
        alert(this.name);
    };

    function Person() {}

    for(prop in Animal.prototype) {
        Person.prototype[prop] = Animal.prototype[prop];
    } // 複製動物的全部屬性到人量邊
    Person.prototype.constructor = 'Person'; // 更新構造函數爲人

3) 構造器應用法

    function Animal() {
        this.name = 'animal';
    }
    Animal.prototype.sayName = function() {
        alert(this.name);
    };

    function Person() {
        Animal.call(this); // apply, call, bind方法均可以.細微區別,後面會提到.
    }
  • 3. js類多重繼承的實現方法是怎麼樣的?

參考答案:就是類繼承裏邊的屬性複製法來實現.由於當全部父類的prototype屬性被複制後,子類天然擁有相似行爲和屬性.

  • 4. js裏的做用域是什麼樣子的?

參考答案:大多數語言裏邊都是塊做做用域,以{}進行限定,js裏邊不是.js裏邊叫函數做用域,就是一個變量在全函數裏有效.好比有個變量p1在函數最後一行定義,第一行也有效,可是值是undefined.

代碼演示

    var globalVar = 'global var';

    function test() {
        alert(globalVar); // undefined, 由於globalVar在本函數內被重定義了,致使全局失效,這裏使用函數內的變量值,但是此時還沒定義
        var globalVar = 'overrided var'; // globalVar在本函數內被重定義
        alert(globalVar); // overrided var
    }
    alert(globalVar); // global var,使用全局變量
  • 5. js裏邊的this指的是什麼?

參考答案: this指的是對象自己,而不是構造函數.

代碼演示

    function Person() {
    }
    Person.prototype.sayName() { alert(this.name); }

    var person1 = new Person();
    person1.name = 'michaelqin';
    person1.sayName(); // michaelqin
  • 6. apply, call和bind有什麼區別?

參考答案:三者均可以把一個函數應用到其餘對象上,注意不是自身對象.apply,call是直接執行函數調用,bind是綁定,執行須要再次調用.apply和call的區別是apply接受數組做爲參數,而call是接受逗號分隔的無限多個參數列表,

代碼演示

    function Person() {
    }
    Person.prototype.sayName() { alert(this.name); }

    var obj = {name: 'michaelqin'}; // 注意這是一個普通對象,它不是Person的實例
    1) apply
    Person.prototype.sayName.apply(obj, [param1, param2, param3]);

    2) call
    Person.prototype.sayName.call(obj, param1, param2, param3);

    3) bind
    var sn = Person.prototype.sayName.bind(obj);    
    sn([param1, param2, param3]); // bind須要先綁定,再執行 
    sn(param1, param2, param3); // bind須要先綁定,再執行
  • 7. caller, callee和arguments分別是什麼?

參考答案: caller,callee之間的關係就像是employer和employee之間的關係,就是調用與被調用的關係,兩者返回的都是函數對象引用.arguments是函數的全部參數列表,它是一個類數組的變量.

代碼演示

    function parent(param1, param2, param3) {
        child(param1, param2, param3);
    }

    function child() {
        console.log(arguments); // { '0': 'mqin1', '1': 'mqin2', '2': 'mqin3' }
        console.log(arguments.callee); // [Function: child]
        console.log(child.caller); // [Function: parent]
    }

    parent('mqin1', 'mqin2', 'mqin3');
  • 8. 什麼是閉包,閉包有哪些用處?

參考答案: 閉包這個術語,不管中文翻譯仍是英文解釋都太2B了,我必須罵人,由於它什麼其實都不是.非要講它是什麼的話,兩個字函數,更多字嵌套函數的父子自我引用關係.全部函數都是閉包.通俗的說,閉包就是做用域範圍,由於js是函數做用域,因此函數就是閉包.全局函數的做用域範圍就是全局,因此無須討論.更多的應用實際上是在內嵌函數,這就會涉及到內嵌做用域,或者叫做用域鏈.說到內嵌,其實就是父子引用關係(父函數包含子函數,子函數由於函數做用域又引用父函數,這它媽不是死結嗎?因此叫閉包),這就會帶來另一個問題,何時引用結束?若是不結束,就會一直佔用內存,引發內存泄漏.好吧,不用的時候就引用設爲空,死結就解開了.

  • 9. defineProperty, hasOwnProperty, propertyIsEnumerable都是作什麼用的?

參考答案:Object.defineProperty(obj, prop, descriptor)用來給對象定義屬性,有value,writable,configurable,enumerable,set/get等.hasOwnProerty用於檢查某一屬性是否是存在於對象自己,繼承來的父親的屬性不算.propertyIsEnumerable用來檢測某一屬性是否可遍歷,也就是能不能用for..in循環來取到.

  • 10. js經常使用設計模式的實現思路,單例,工廠,代理,裝飾,觀察者模式等

參考答案:

    1) 單例: 任意對象都是單例,無須特別處理
    var obj = {name: 'michaelqin', age: 30};

    2) 工廠: 就是一樣形式參數返回不一樣的實例
    function Person() { this.name = 'Person1'; }
    function Animal() { this.name = 'Animal1'; }

    function Factory() {}
    Factory.prototype.getInstance = function(className) {
        return eval('new ' + className + '()');
    }

    var factory = new Factory();
    var obj1 = factory.getInstance('Person');
    var obj2 = factory.getInstance('Animal');
    console.log(obj1.name); // Person1
    console.log(obj2.name); // Animal1

    3) 代理: 就是新建個類調用老類的接口,包一下
    function Person() { }
    Person.prototype.sayName = function() { console.log('michaelqin'); }
    Person.prototype.sayAge = function() { console.log(30); }

    function PersonProxy() { 
        this.person = new Person();
        var that = this;
        this.callMethod = function(functionName) {
            console.log('before proxy:', functionName);
            that.person[functionName](); // 代理
            console.log('after proxy:', functionName);
        }
    }

    var pp = new PersonProxy();
    pp.callMethod('sayName'); // 代理調用Person的方法sayName()
    pp.callMethod('sayAge'); // 代理調用Person的方法sayAge() 

    4) 觀察者: 就是事件模式,好比按鈕的onclick這樣的應用.
    function Publisher() {
        this.listeners = [];
    }
    Publisher.prototype = {
        'addListener': function(listener) {
            this.listeners.push(listener);
        },

        'removeListener': function(listener) {
            delete this.listeners[listener];
        },

        'notify': function(obj) {
            for(var i = 0; i < this.listeners.length; i++) {
                var listener = this.listeners[i];
                if (typeof listener !== 'undefined') {
                    listener.process(obj);
                }
            }
        }
    }; // 發佈者

    function Subscriber() {

    }
    Subscriber.prototype = {
        'process': function(obj) {
            console.log(obj);
        }
    }; // 訂閱者


    var publisher = new Publisher();
    publisher.addListener(new Subscriber());
    publisher.addListener(new Subscriber());
    publisher.notify({name: 'michaelqin', ageo: 30}); // 發佈一個對象到全部訂閱者
    publisher.notify('2 subscribers will both perform process'); // 發佈一個字符串到全部訂閱者
  • 11. 列舉數組相關的經常使用方法

參考答案: push/pop, shift/unshift, split/join, slice/splice/concat, sort/reverse, map/reduce, forEach, filter

  • 12. 列舉字符串相關的經常使用方法

參考答案: indexOf/lastIndexOf/charAt, split/match/test, slice/substring/substr, toLowerCase/toUpperCase

相關文章
相關標籤/搜索