1. 程式人生 > 其它 >javascript中的物件

javascript中的物件

1 建立物件

在js中建立物件非常的簡單

var obj={}

這樣,我們就建立了一個物件

2 物件的繼承

在ES6之前,javascript物件的繼承是通過原型(prototype)來實現的。在ES6之後的繼承方式類似於java

2.1 方式1 通過prototype建立物件

舉例

var student = {
    name: 'no_name',
    height: 1.2,
    run: function () {
        console.log(this.name + ' is running...');
    }
};

var xiaoming = {
    name: 
'小明' }; xiaoming.__proto__ = student;

訪問屬性和方法

xiaoming.name; // '小明'
xiaoming.run(); // 小明 is running...

xiaoming有自己的name屬性,但並沒有定義run()方法。不過,由於小明是從student繼承而來,只要studentrun()方法,xiaoming也可以呼叫

需要注意的是,上述示例只用於演示,在平時開發過程中不要直接用obj.__proto__去改變一個物件的原型。

2.2 通過Object.create()建立物件

var xiaoming=Object.create(student)
xiaoming.name
='小明' //判斷原型是否是student xiaoming.__proto__===student // 返回true

2.3 通過建構函式建立物件

定義一個建構函式

function Student(name) {
    this.name = name;
    this.hello = function () {
        alert('Hello, ' + this.name + '!');
    }
}

咦,這不就是一個普通函式嗎。是的,這確實就是一個普通函式,但是如果我們通過如下方式使用,則這個普通函式就是一個建構函式

//通過建構函式建立一個新的物件
var xiaoming=new
Student('小明') //呼叫 xiaoming.name; // '小明' xiaoming.hello(); // Hello, 小明!

新建立的xiaoming的原型鏈是:

xiaoming ----> Student.prototype ----> Object.prototype ----> null

3 原型鏈

當我們用obj.xxx訪問一個物件的屬性時,JavaScript引擎先在當前物件上查詢該屬性,如果沒有找到,就到其原型物件上找,如果還沒有找到,就一直上溯到Object.prototype物件,最後,如果還沒有找到,就只能返回undefined

例如

var arr = [1, 2, 3];

其原型鏈是

arr ----> Array.prototype ----> Object.prototype ----> null

再比如

function foo() {
    return 0;
}

函式也是一個物件,它的原型鏈是:

foo ----> Function.prototype ----> Object.prototype ----> null

4 constructor屬性

new Student()建立的物件還從原型上獲得了一個constructor屬性,它指向函式Student本身

xiaoming.constructor === Student.prototype.constructor; // true
Student.prototype.constructor === Student; // true
Object.getPrototypeOf(xiaoming) === Student.prototype; // true
xiaoming instanceof Student; // true

這是什麼亂七八糟的,看暈了,請看下圖

其中紅色箭頭是原型鏈,注意,

建構函式Student.prototype指向的物件就是xiaoming的原型物件,這個原型物件自己還有個屬性constructor,指向Student構造函式本身。

另外,建構函式Student恰好有個屬性prototype指向xiaoming的原型物件,但是xiaoming物件可沒有prototype這個屬性,不過可以用__proto__這個非標準用法來檢視。

不過還有個問題

xiaoming.name; // '小明'
xiaohong.name; // '小紅'
xiaoming.hello; // function: Student.hello()
xiaohong.hello; // function: Student.hello()
xiaoming.hello === xiaohong.hello; // false

xiaoming和xiaohong各自的name不同,這是對的

但是xiaoming和xiaohong各自擁有獨立的hello()方法,這就不合理了,這樣浪費了很多記憶體。解決方法是有的,就是通過上圖的原型鏈關係圖,我們如果把hello()方法移動到他們共同的原型上就可以了,如下圖

把hello()方法移動到上圖中的"某個物件"裡,而這個"某個物件"就是Student.prototype,因此我們把hello()方法移動到Student.prototype上。

修改程式碼如下

function Student(name) {
    this.name = name;
}

Student.prototype.hello = function () {
    alert('Hello, ' + this.name + '!');
};