2016年11月21日 星期一

物件導向 (JavaScript 7)

※Object

Object 屬性 方法 繼承

let o = {
    id:5,
    name:function(){
        return "bruce";
    },
    set nid(id){
        this.id = id;
    },
    get nid(){
        return this.id;
    }
};
    
console.log(o.id); // 5
o.nid = 100;
console.log(o.id); // 100
console.log(o.nid); // 100
    
let o_child = Object.create(o); // 繼承
console.log(o_child.nid); // 100

※set get 取名時不能和已有的 key 相同

※set 只能剛好有一個參數; get 不能有參數

※使用["name"]這種方式也行,裡面可以有特殊符號、空格,甚至還可以是變數



set/get 方法名稱為變數

let variable = "nid";
let o = {
    id:5,
    name:function(){
        return "bruce";
    },
    set [variable](id){
        this.id = id;
    },
    get [variable](){
        return this.id;
    }
};
    
console.log(o.id); // 5
o.nid = 100;
console.log(o.id); // 100
console.log(o.nid); // 100
    
let o_child = Object.create(o);
console.log(o_child.nid); // 100

※主要看 o.id 有沒有變化
因為 o.nid 本來就可以在物件外給 key-value,如果 set 沒成功,o.id 和 o_child.id 的值會是 5



var

// var o = {
//     id:6
// };
    
var o = o || {
    id:5,
    name:function(){
        return "bruce";
    },
    set nid(id){
        this.id = id;
    },
    get nid(){
        return this.id;
    }
};
    
console.log(o.id); // 5
o.nid = 100;
console.log(o.nid); // 100
    
let o_child = Object.create(o);
console.log(o_child.nid); // 100

※如果宣告用 var 的話,還可以用 var o = o || {};,表示如果已經有 o 這個變數就用,不然就用空的,但用 const 或 let 都不行



※function

return 物件

function Xxx(){
    this.name = "x";
    // return 10;
    // return {a:1};
}
    
var x = new Xxx();
console.log(x.name);// x
// console.log(new Xxx());// Xxx {name: "x"}
// console.log(x.a);

※寫了 this.xxx 而且不管有沒有寫 return 一般的值,這兩者都可以 new 後直接.屬性/方法

※寫了 this.xxx 而且寫了 return 物件或 funtion,那 new 後直接.屬性和.方法不加「()」會是undefined,但可內部調用



function 屬性 方法 繼承

function X(){
    this.id = 5;
    this["name"] = function() {
        return "bruce";
    },
    this.setId = function(id) {
        this.id = id;
    }
    this.getId = function() {
        return this.id;
    }
}
    
let xxx = new X();
console.log(xxx.id);
xxx.setId(50);
console.log(xxx.getId());
    
function x_child(){}
x_child.prototype = new X(); // prototype 繼承
let x_child2 = Object.create(new X()); // Object 繼承
    
let x_child1 = new x_child();
console.log(x_child1.getId());
console.log(x_child2.getId());

※「.」也可用「[ ]」

※function 有兩種繼承

※如果在 function 內宣告 var 屬性和方法,只能內部調用,外面呼叫都是 undefined



新增/修改屬性、方法

function X(){
    this.id = 5;
    this["name"] = function() {
        return "bruce";
    },
    this.setId = function(id) {
        this.id = id;
    }
    this.getId = function() {
        return this.id;
    }
}
    
X.prototype.method = function(){
    return "method";
}
    
let xxx = new X();
console.log(xxx.method()); // method
    
function x_child(){}
x_child.prototype = new X(); // prototype 繼承
let x_child2 = Object.create(new X()); // Object 繼承
    
let x_child1 = new x_child();
console.log(x_child1.method()); // method
console.log(x_child2.method()); // method

※可以在 function 外直接新增,使用 function名稱.prototype.方法或屬性即可

※注意寫在 function 外的屬性和方法可以一直覆蓋下去,但本來就在 function 裡的屬性和方法,並不會覆蓋,而且也不會報錯

※宣告的 prototype 上面可加個 if 判斷,如 if(!X.prototype.method),沒有的才做,可以避開瀏覽器不支援的情形



一次新增多個屬性、方法

function X(){
    this.id = 5;
    this["name"] = function() {
        return "bruce";
    },
    this.setId = function(id) {
        this.id = id;
    }
    this.getId = function() {
        return this.id;
    }
}
    
// X.prototype.method1 = function(){
//     return "method1";
// }
    
// X.prototype.method2 = function(){
//     return "method2";
// }
    
X.prototype = {
    method1 : function(){
        return "method1";
    },
    method2 : function(){
        return "method2";
    },
};
    
let x = new X();
console.log(x.method1()); // method1
console.log(x.method2()); // method2

※當然還是會後者蓋前者



※class

class 繼承

class SonDate extends Date {
    xxx() {
        return "xxx";
    }
}
    
let son = new SonDate();
console.log(son.getDate());
console.log(son.xxx());

※由於繼承了內鍵的 Date,所以可以用它的方法

※也可以繼承自己寫的 class

※只能在方法裡寫變數(this.xxx、var xxx 都一樣)



class getter/setter constructor

class SonDate {
    xxx(){
        return this.id + "-" + this.name;
    }
    
    constructor(id, name) {
        this.id = id;
        this.name = name;
    }
    
    get abc(){
        return this.id;
    }
    
    set abc(id){
        this.id = id;
    }
}
    
let son = new SonDate(7, "mary");
console.log(son.xxx()); // 7-mary
console.log(son.abc); // 7
son.abc = 50;
console.log(son.abc); // 50

※set get 取名時不能和屬性相同

※如果有繼承,而且寫了 constructor ,那第一行就一定要寫 super(),當然參數就看繼承誰了

※最多只能有一個 constructor



set/get 方法名稱為變數

let variable = "abc";
    
class SonDate {
    xxx(){
        return this.id + "-" + this.name;
    }
    
    constructor(id, name) {
        this.id = id;
        this.name = name;
    }
    
    get [variable](){
        return this.id;
    }
    
    set [variable](id){
        this.id = id;
    }
}
    
let son = new SonDate(7, "mary");
console.log(son.xxx()); // 7-mary
console.log(son.abc); // 7
son.abc = 50;
console.log(son.abc); // 50

※主要看第二個 son.abc,失敗的話是 undefined



static

class SonDate {
    static method() {
        return SonDate.xxx();
    }
    
    static xxx() {
        return "x1";
    }
    
    xxx() {
        return "x2";
    }
}
    
console.log(SonDate.method()); // x1

※static 呼叫 static,要用「類.static 方法名」(java直接呼叫 static 方法名);
呼叫 non static 用 new

※static 不能寫屬性

※如果有繼承,還可用 super.父類方法名

沒有留言:

張貼留言