JavaScript學習(二)——深刻學習js對象的原型與繼承

瞭解對象

 什麼是對象?
 
…… 這個就不說了

對象的聲明的兩種方式

 

 1 var person = new Object(); 
 2 person.name="linchen"; 
 3 person.age="18"; 
 4 person.job="java";
 5 
 6 var person={ 
 7 name:"linchen", 
 8 age:"18", 
 9 job:"java" 
10 }

 

 

對象的數據屬性和訪問器屬性

懶得寫了,這騷操做沒啥用,給出相關連接:
https://blog.csdn.net/qq_17371033/article/details/52688195 
 

建立對象

 

構造函數

構造函數也是函數,是比較特殊的函數。 
這種函數是用來建立對象的,就比如普通函數最後return一個對象同樣。 
區別在於構造函數沒有顯式的建立對象,直接將屬性和方法賦給了this,沒有return語句。
css

例: 
html

 

//構造函數:

    // 物質(屬性:質量,速度,是否生物)
    function Material(quality,speed,isLivingText) {
        this.quality = (quality||0) + "kg";
        this.speed = (speed||0) + "m/s";
        this.isLiving = isLivingText == "生物";
        this.setSpeed = function(num) {
            this.speed = num + "m/s";
        }
    }
    // 建立一個對象,須要用new關鍵字
    var body1=new Material(50,5,"生物");
    var body2=new Material(100,0,"非生物");

//用普通函數建立對象:

    function material(quality,speed,isLivingText) {
        var obj={};
        obj.quality = (quality||0) + "kg";
        obj.speed = (speed||0) + "m/s";
        obj.isLiving = isLivingText == "生物";
        obj.setSpeed = function(num) {
            obj.speed = num + "m/s";
        }
        return obj;
    }
    var body3=material();
    var body4=material(100,0,"非生物");

 

這種用函數來封裝以特定接口建立對象的細節的模式被稱爲工廠模式 
經過new關鍵字來建立對象的模式被稱爲構造函數模式
java

 

原型對象

一、任何函數都有一個屬性:prototype (原型)jquery

prototype指向一個原型對象chrome

該原型對象包含由該構造函數建立的全部實例共享的屬性和方法。app

 

二、任何對象都有一個隱藏的屬性: __proto__dom

__proto__屬性的值指向該構造函數的原型對象。ide

 

三、任何原型對象都有一個屬性:constructor (構造函數)函數

constructor指向該原型對象對應的構造函數。ui

 

四、原型對象也是對象,也會有一個__proto__屬性

假如原型對象是另外一個構造函數的實例,則造成原型鏈。

原型鏈的終點必是構造函數Object()的原型

其原型的__proto__屬性值爲null

 

五、原型對象的設置方法:

 1         // 修改單個屬性或方法
 2         Material.prototype.quality="0kg";
 3         Material.prototype.setQuality = function(num) {
 4              this.quality = num + "kg";
 5         };
 6 
 7         // 初始化原型對象
 8         Material.prototype={
 9             quality:"0kg",
10             setQuality:function(num) {
11                  this.quality = num + "kg";
12             };
13         }
14 
15         // 原型對象是另外一個對象的實例
16         Material.prototype=new Object();

 

六、原型對象是動態的,當咱們對原型對象所作了任何修改都會在全部實例上反映出來。 
例:

1 var body1=new Material();
2 body1.setSpeed(20); //body1.setSpeed is not a function
3 console.log(body1.speed);
4 Material.prototype.setSpeed=function(num){
5     this.speed=num+"m/s";
6 }
7 body1.setSpeed(40);
8 console.log(body1); // 40m/s

 

 

繼承

 

什麼是繼承

一個對象得到另外一個對象的全部屬性和方法,這個操做叫作繼承。

 

原型式繼承

當構造函數a的原型等於構造函數b的實例時,造成一個原型鏈,經過這樣的方式,a就擁有了b全部的屬性和方法,這種方式叫作構造函數繼承。

缺點: 
a建立出來的實例的繼承於b的屬性和方法都是共享的,改了其中一個實例的屬性值,別的實例對應的屬性值也會改變。

 

寄生式繼承

經過在構造函數a中調用構造函數b來使a擁有了b全部的屬性和方法。這種方式叫作寄生式繼承。

使用apply()和call():

function B(name){
    this.name=name;
}
function A(name,age){
    B.call(this,name);
    // B.apply(this,[name])
    this.age=age;
}

apply()與call()詳解: 
http://www.javashuo.com/article/p-xvglmgjq-br.html (別人寫的)

缺點: 
a建立出來的實例不繼承b的原型的屬性和方法。若是把b的原型的屬性和方法都寫在b裏面也就失去了函數複用的能力了。

 

組合繼承(寄生組合式繼承)

先使用寄生式繼承來繼承,再使用原型式繼承。解決了以上兩種方式各自的缺點。實例上的屬性和方法會屏蔽原型上相同名的屬性和方法。

 

demo

把下面代碼複製到一個新建的.html文件,記得引入jquery,打開控制檯看console

  1 <!DOCTYPE html>
  2 <html>
  3 
  4 <head>
  5 <meta charset="utf-8">
  6 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  7 <title>Examples</title>
  8 <meta name="description" content="">
  9 <meta name="keywords" content="">
 10 <link href="" rel="stylesheet">
 11 <script src="jquery1.42.min.js"></script>
 12 </head>
 13 
 14 <body>
 15 <div id="box1"></div>
 16 <!-- 構造函數,實例 -->
 17 <script id="js1">
 18     // 構造函數,實例--------------------------------------------------
 19     /**
 20         按照慣例:
 21             一、構造函數始終都應該以一個大寫字母開頭
 22             二、非構造函數則應該以一個小寫字母開頭
 23 
 24         與普通函數的區別:
 25             一、沒有顯式地建立對象
 26             二、直接將屬性和方法賦給了this對象
 27             三、沒有return語句
 28     */
 29 
 30     // 物質(屬性:質量,速度,是否生物)
 31     function Material(quality,speed,isLivingText) {
 32         this.quality = (quality||0) + "kg";
 33         this.speed = (speed||0) + "m/s";
 34         this.isLiving = isLivingText == "生物";
 35         this.setSpeed = function(num) {
 36             this.speed = num + "m/s";
 37         }
 38     }
 39 
 40     // 這種用函數來封裝以特定接口建立對象的細節的模式被稱爲工廠模式
 41     //  function material(quality,speed,isLivingText) {
 42     //      var obj={};
 43     //     obj.quality = (quality||0) + "kg";
 44     //     obj.speed = (speed||0) + "m/s";
 45     //     obj.isLiving = isLivingText == "生物";
 46     //     obj.setSpeed = function(num) {
 47     //         obj.speed = num + "m/s";
 48     //     }
 49     //     return obj;
 50     // }
 51 
 52     // 建立實例,獲得一個新對象
 53     var body1 = new Material(50,0,"生物");
 54     console.log(body1);
 55 
 56     // 繼承----------------------------------------------------------
 57     /**
 58      * 繼承的方式:
 59      *  一、原型鏈(主要)(原型式繼承)
 60      *  二、借用構造函數(寄生式繼承)
 61      *  三、1和2組合繼承 (寄生組合式繼承)
 62      */
 63 
 64     // 設置質量的方法(原型)
 65     Material.prototype.setQuality = function(num) {
 66         this.quality = num + "kg";
 67     };
 68     // 經過對象
 69     Material.prototype.setOption = function(opt) {
 70         opt = opt || {};
 71         this.quality = (opt.quality || 0) + "kg";
 72         this.speed = (opt.speed || 0) + "m/s";
 73         this.isLiving = opt.isLivingText == "生物";
 74     };
 75     // 速度參照物(原型)
 76     Material.prototype.reference = "地球表面";
 77     body1.setQuality(25);
 78     console.log(body1);
 79 
 80     // 非生物(構造函數)
 81     function NonLivingThings() {
 82 
 83     }
 84     // 原型式繼承
 85     NonLivingThings.prototype = new Material(null,null,"非生物");
 86     NonLivingThings.prototype.constructor = NonLivingThings;
 87     var nonLifeBody1 = new NonLivingThings();
 88     console.log(nonLifeBody1);
 89 
 90     // 生物(構造函數)
 91     function LivingThings() {
 92         // 寄生式繼承
 93         Material.call(this,null,null,"生物"); //(call寫法)
 94         // Material.apply(this, ["生物"]);(apply寫法)
 95         this.lifeSpan = 0 + "";
 96     }
 97     // 原型式繼承 -- 由於前面已經實現了寄生式繼承,因此實現了寄生組合式繼承
 98     // LivingThings.prototype = new Material("生物");
 99     // LivingThings.prototype.constructor = LivingThings;
100     // 重寫原型的setOption函數
101     // LivingThings.prototype.setOption = function() {
102     //     return function(opt) {
103     //         LivingThings.prototype.setOption.call(this, opt);
104     //         this.lifeSpan = (opt.lifeSpan || 0) + "年";
105     //     }
106     // }
107     var lifeBody1 = new LivingThings();
108     // lifeBody1.setOption({
109     //     "quality": 20,
110     //     "lifeSpan": 100
111     // });
112     console.log(lifeBody1);
113 </script>
114 <script id="js2">
115     // 建立一個對象,名爲石頭
116     var 石頭 = new NonLivingThings("非生物");
117     石頭.setOption({
118         "speed": 100
119     });
120     // 給物質添加一個run函數,傳入節點,實現該節點塊從左往右滑動
121     Material.prototype.run = function(dom) {
122         var $dom=$(dom);
123         $dom.css({
124                 width: "100px",
125                 height: "100px",
126                 background: "red"
127             });
128             $dom.animate({
129             marginLeft: '+500px'
130         }, (500 / parseInt(this.speed || 100)) * 1000);
131 
132     };
133     石頭.run("#box1");
134 </script>
135 </body>
136 
137 </html>
相關文章
相關標籤/搜索