[JavaScript] 物件導向寫法

程式語言:JavaScript

簡介:如何宣告和應用

function Obj(y) 
{
    // public 可被繼承
    this.x = 10;        // 第一種寫法
    this["y"] = y;      // 第二種寫法
    this.z = function() // 新增 z function
    { 
        console.log(this.x)
        console.log(this.y)
        console.log(a) // >> 3
        return this.x; 
    }
    
    // private 只可見於 function 內,不可被繼承,外部無法使用
    var a = 3;
    var b = function()
    { 
        console.log(a)
        return a; 
    }
}
Obj.xx = 10;         // 第三種寫法
Obj.["yy"] = "yy";   // 第四種寫法

var obj = new Obj("y")
console.log(obj.a) // >> undefined
obj.z() // >> 10, 'y', 3

同樣名字的變數,子物件會覆蓋母物件,但若是 private 的,則會維持
呼叫時,尋找的方式為 子 -> 母 -> 祖 -> ...,直到找不到則回傳 undefined
function Inherit(x, y, t) // inherit from Obj
{
    this.prototype = Obj; // 無法使用 new Obj(y)
    this.prototype(y); //初始化 Obj

    this.x = 100; // 覆蓋母物件 Obj 的 x
    this.t = t;
    a = 5 // 不會更改母物件 Obj 的 a
}
// Inherit.prototype = new Obj(y); // 在外部可使用

var inherit = new Inherit(1, "z", 30)
// z() 原為 >> 10, 'y', 3
inherit.z() // >> '100', 'z', 3 // a 仍然為 3
inherit.prototype.all = 3 // Inherit 加入 all 變數,原型已被更改
inherit.only = 3 // inherit 加入 only 變數,原型未更改

prototype

prototype 是個物件
檢查是否存在屬性的 hasOwnProperty,也是在 prototype 中
故所有物件皆有此 function
var prototypeType = typeof Object.prototype
console.log(prototypeType); // >> object

var hasOwn = Object.prototype.hasOwnProperty("hasOwnProperty");
console.log(hasOwn); // >> true

This 討論

this 的決定,依誰呼叫為主
  • 物件.函式()   => 函式內的 this 指向該物件
  • New 物件      => 建立時 this 指向該物件
  • 函式()            => 函式內的 this 指向全域物件,也就是 window
function A()
{
    this.b = 'a'
    console.log(this)
}
A() // >> window
a = new A() // >> Object { b: "a" }

簡單範例:
因 foo() 前,無調用物件,故為 window
var A = {
    f: function ()
    {
        console.log(this); // >> Object { f: A.f() }
        var foo = function ()
        {
            console.log(this);
        }
        foo(); // >> window
    }
};
A.f();
// Output
// >> Object { f: A.f() }
// >> window

複雜範例:
var x = 'window';
var A = {
   x:'A',
   f: function(){ console.log(this.x); }
};

A.f(); // >> A

var fOut = A.f;
fOut(); // >> window

var B = {
    x:'B',
    f : A.f
}

B.f(); // >> B

若無法確定 this,建議直接指定,可用 call or apply
兩者差異只在傳入的參數方式不同
//函式的 this 指向 B物件(若 B物件為 null,則指向全域物件) 
(A物件.)函式.call(B物件,參數1,參數2,參數3, ......);

//函式的 this 指向 B物件(若 B物件為 null,則指向全域物件) 
(A物件.)函式.apply(B物件,[參數1,參數2,參數3, ......]); 

留言