2020年3月1日 星期日

Javascript OOJS 物件導向JS

prototype 語言

Javascript 是基於 prototype 的語言,
意思是他是利用 prototype 建立起整個語言架構。

有一個最基礎的 null,
然後所有物件的基礎物件 Object 就是繼承自 null 這個 prototype,
Object 本身自己有一個 prototype 屬性,
這個屬性是他讓別人繼承的,
也就是別的物件要繼承自 Object 時,
他其實繼承的是 Object 的 prototype 屬性(這個屬性裡可以包含很多東西)。

所以用 Javascript 寫的程式,
就是這樣,一個物件繼承自另一個物件的 prototype 屬性,逐步建立起整個程式。

建立物件的方式一:function 回傳物件

利用函式回傳一個物件。
沒彈性,而且每一個物件都是 object。

function createNewPerson(name) {
  var obj = {};
  obj.name = name;
  obj.greeting = function () {
    alert('Hi! I\'m ' + this.name + '.');
  }
  return obj;
}

建立物件的方式二:Object()建構子

//new Object() 建立空白物件
//再把屬性加上去
var person1 = new Object();
person1.name = 'Chris';
person1['age'] = 38;
person1.greeting = function() {
  alert('Hi! I\'m ' + this.name + '.');
}


//或是直接傳入一個物件當參數
var person1 = new Object({
  name : 'Chris',
  age : 38,
  greeting : function() {
    alert('Hi! I\'m ' + this.name + '.');
  }
});

建立物件的方式三:Object.create() 函式 IE8不支援



var person2 = Object.create(person1);

//person2.name
//person2.greeting()

建立物件的方式四:建構子函式 constructor function

WDN
Constructor funciton 是一種特殊的函式,
用來建立物件。
比用傳統方式建立物件好很多。

function Person(name,interests) {
  this.name = name;
  this.interests=interests;
  this.greeting = function() {
    alert('Hi! I\'m ' + this.name + '.');
  };
}

var person1 = new Person('Bob',[1,2,3]);
var person2 = new Person('Sarah',[1,2,3]);

console.log(person1['name']);        //可以這樣取
console.log(person1.interests[1]);   //可以這樣取
console.log(person1.greeting());
console.log(person2.name);
console.log(person2.greeting());

用建構子函式實體化的物件

建構子函式實體化的物件,
建構子函式定義的prototype屬性,只會有一份,
不會複製到每個實體上。

繼承(更接近於delegate 委託)

Javascript 的繼承,是[原型繼承](Prototypal inheritance)。
子物件不會把父物件可繼承的屬性複製過來,
而是用原型鍊連結他繼承的屬性。
子物件的繼承其實不是繼承,而是連接,
連接父物件prototype屬性。
所以一個父物件,不管延伸出多少子物件,
子物件繼承的屬性都只有一份,
就是存在父物件 prototype 屬性的那份。

  • 繼承方式一:實體化一份父物件,但是owner設成自己


  •    
      //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
         
        var t=new Teacher("a","b",3,1,"book","math");
        console.log(t.name);     //{"a","b"}
    
    



  • 繼承方式二:繼承父物件的 prototype 屬性


  • 每個物件的 prototype 屬性,是要繼承下去的。
    所以父物件的 prototype 屬性要連結在子物件的 prototype 屬性上。
    而子物件要讓孫物件繼承的屬性,也加到自己的 prototype 屬性上。



     
       //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            alert('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
       //繼承父物件的 prototype 屬性
       Teacher.prototype=Object(Person.prototype);
      //**記得要把 constructor 設成自己,否則會是 Person 
       Teacher.prototype.constructor = Teacher;    
    
       var t=new Teacher("a","b",3,1,"book","math");
       console.log(t.name);     //{"a","b"}
       console.log(t.greeting());   //繼承自父物件的屬性
    
    

    複寫繼承自父物件的屬性

     
       //父物件
       function Person(first, last, age, gender, interests) {
            this.name = {
              first,
              last
            };
            this.age = age;
            this.gender = gender;
            this.interests = interests;
          };
    
        Person.prototype.greeting = function() {
            console.log('Hi! I\'m ' + this.name.first + '.');
          };
    
    
        //子物件
        function Teacher(first, last, age, gender, interests, subject) {
           
           //用call 呼叫實體化父物件,把this 傳進去當作owner
            Person.call(this, first, last, age, gender, interests);
           
          //Teacher 新增的屬性
           this.subject=subject;
       }
       
       
       //繼承父物件的 prototype 屬性
       Teacher.prototype=Object(Person.prototype); 
       //**記得要把 constructor 設成自己,否則會是 Person
       Teacher.prototype.constructor = Teacher; 
    
       //複寫父物件的 greeting
       //**要在 Teacher.prototype=Object(Person.prototype) 之後,才有複寫到
       Teacher.prototype.greeting=function(){
             console.log('Hi! I\'m teacher.');
       }   
    
       var t=new Teacher("a","b",3,1,"book","math");
       console.log(t.name);     //{"a","b"}
       console.log(t.greeting());   //變成自己的屬性
    
    

    沒有留言:

    張貼留言