Javascript漂流記(上)__原型、原型鏈、toString、call/apply

一、原型:是function對象的一個屬性,是構造函數製造出對象的公共祖先。通過該構造函數產生的對象,可以繼承原型的屬性和方法。原型也是對象。
    
       提取公有屬性:

        //Person.prototype = {},生來就有,是person1,person2...的爹
        Person.prototype = {
            //constructor : Person,
            lastName : 'James',
            firstName : 'Lebron',
            gender : 'male',
            age : 36
        }
        function Person(club,score){
            //var this = {
            //    __proto__ : Person.prototype(在person1訪問屬性時,如果自己身上沒有,就會沿着__proto__的指向去找)      
            //}
            this.club = club;
            this.score = score;
            //return this;
        }
        var person1 = new Person('Laker', 10000);
        var person2 = new Person('Heat', 8000);

        增:Person.prototype.wife = 'Laurel';
        刪:delete Person.prototype.lastName; 從person1下手是刪不掉
        改:Person.prototype.lastName = 'King'; 在person1身上是改不掉的,除非是引用值的調用式修改,詳情看下文。
        查:person1.lastName;
        Person.prototype生來有constructor屬性,指向Person(),可以手動更改。
        其中person1可以通過person1.constructor找到構造它的函數Person()。


二、原型鏈:

        //Grand.prototype.__proto__ = Object.prototype
        //Grand.prototype.lastName = 'James';
        function Grand(){}
        var grand = new Grand();

        Father.prototype = grand;
        function Father(){
            this.fisrtName = 'Lebron';
            this.club = {
                no1 : 'Heat',
                no2 : 'Laker'
            }
        }
        var father = new Father();
    
        Son.prototype = father;
        function Son(){
            this.hobbit = 'basketball';
        }
        var son= new Son();

       增刪改查,類似原型增刪改查
       說到其中的改:son.club.no3 = 'Rocket'; 可以實現引用值的調用式修改。


       1、另一種構造對象的方式:

            var obj = Object.create(原型)

            絕大多數對象的最終都會繼承自Object.prototype(Object.create(null)是個例外)。

       2、關於toString(),觀察下列代碼輸出。

            Object.prototype上本身含有toString方法,但輸出形式是"[object Xxxxx]",爲何數字,字符串,數組,布爾會輸出不同形式?

        123.toString();//會報錯,首先識別成浮點型

        var num = 123;
        num.toString();    //返回"123"

        var str = 'abc';
        str.toString();    //返回"abc"

        var arr = [1,2];
        arr.toString();    //返回"1,2"

        var obj = {};
        obj.toString();    //返回"[object Object]"

       拿數字舉例,儘管Number.prototype.__proto__ = Object.prototype。但Number.prototype上有重寫的toString方法,並不會調用Object.prototype本身的方法。同樣:
        String.prototype上有重寫的toString方法
        Array.prototype上有重寫的toString方法
        Boolean.prototype上有重寫的toString方法

        如何來證明呢?還記得初學JavaScript使用過的document.write。我們來看一下它的底層原理。

        var obj = Object.create(null);
        document.write(obj);//會報錯
        var obj = Object.create(null);
        //因爲此時的obj對象沒有prototype,也不存在toString方法,我們爲其手動添加。
        obj.toString = function(){
	        return '呵呵呵';
        }
        document.write(obj);//打印結果爲呵呵呵。證明調用的是toString

         3、JavaScript小bug:0.14 * 100 = 14.000000000000002
               是由於JavaScript精度不準造成的,正常計算的範圍是小數點前後各16位。我們應該儘量避免小數操作,如果不能避免,可以使用Math.floor/Math.ceil。

三、call和apply,改變this指向,傳參列表不同

        function Person(name, age, gender){
            //this == obj
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
        var person = new Person('James', 36, 'male');
        var obj = {};
        //Person(); === Person.call();
        Person.call(obj, 'Lau', 128, 'male');

       在開發過程中,想用別人的方法實現自己的功能怎麼辦,還用說,call它啊,參數第一位把填自己的對象。
       如下列代碼,想要借用上圖Person的方法來實現自己的功能,可按照下列操作。

        function Student(tel, grade){
            //var this = {__proto__ : Student.prototype}
            Person.call(this, name, age, gender);
            this.tel = tel;
            this.grade = grade;
        }
        var student = new Student('Jack', 128, 'male', 17600001234, 2019);

        call和apply的唯一不同之處在於傳參列表,apply的傳參形式爲arguments。

以上內容屬二哥原創,整理自 "渡一教育Javascript課程" ,一個值得推薦的"渡一教育"。

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