【重溫基礎】15.JS物件介紹

pingan8787發表於2019-01-14

從這篇文章開始,複習 MDN 中級教程 的內容了,在初級教程中,我和大家分享了一些比較簡單基礎的知識點,並放在我的 【Cute-JavaScript】系列文章中。

關於【Cute-JavaScript
一本可愛的JavaScript小書,內容分成三大部分:ES規範系列JS基礎系列面試題系列,目前我還在抓緊更新,喜歡的朋友可以 github 上Star一下呀,下面放一張首頁圖:
Cute-JavaScript


正文開始

本文是 重溫基礎 系列文章的第十五篇。
今日感受:耐心為人處世。

本章節複習的是JS中的關於物件還有原型等相關知識。

前置知識
關於使用物件,可以先閱讀一下我的《12.使用物件》這篇文章。

下面也先重溫一點基礎。

1.概念

物件是一個包含相關資料和方法的集合,由變數方法組成,通常稱為物件的屬性方法,比如:

let me = {
    name : `pingan`,
    eat: function(){
        console.log(`eat eat eat!!!`);
    }
}

其中,name就是me這個物件的一個屬性,eat就是me這個物件的一個方法。
訪問物件的屬性是這樣的:

me.name;   // "pingan"
me.eat();  // "eat eat eat!!!"

另外在訪問物件屬性時,有以下兩種方式:

let me = {
    name : `pingan`,
}
// 點表示法
me.name;   // me.name => "pingan"

// 括號表示法
me["name"];// me.name => "pingan"

括號表示法中,必須是字串。

我們常常這麼設定物件的屬性:

let me = {
    name : `pingan`,
}
// 點表示法
me.name = "leo";   // me => {name: "leo"}

// 括號表示法
me["name"] = "leo";// me => {name: "leo"}

2.簡單的物件導向介紹

這裡簡單介紹下JavaScrip的物件導向程式設計OOP。

物件導向程式設計(Object Oriented Programming,OOP,物件導向程式設計)是一種計算機程式設計架構。OOP 的一條基本原則是計算機程式是由單個能夠起到子程式作用的單元或物件組合而成。 —— 百度百科

OOP

我們這裡定義一個簡單的物件模型,比如我,我的身上可能有很多資訊(姓名,年齡,身高等等),這時候我們可以將這些資訊抽取出來,像這樣:

let leo = {
    name : `leo`,
    age  : 26,
    height : 180,
}

這樣我們就將我的資訊抽取成一個JS的物件了,但是這樣有個侷限性,這樣定義的話,一次只能定義一個人,如果這時候,有一百個人,那麼我們就需要定義一百個這樣的物件,顯然這是不可取的。
所以,這裡就引入一個重要的函式——建構函式將相同的特性封裝成通用的物件,實現定義一次,其他地方都可以使用,這也是OOP的核心思想:

// 傳入 name 引數使得可以定義任何人作為物件
function Person (name){
    let me = {};
    me.name = name;
    me.doSomething = function(){
        console.log(me.name);
    }
    return me;
}

建立一個函式“Person”,只要傳入不同的name即可得到不同的物件:

let leo = Person("leo");
leo.name;    // "leo"

let pingan = Person("pingan");
pingan.name; // "pingan"

但是似乎Person物件的定義,顯得不夠精簡,因為還要定義一個空物件來接收各個屬性和方法,幸好JavaScrip在建構函式中提供一個便捷的方法,我們將程式碼改造下:

function Person (name){
    this.name = name;
    this.doSomething = function(){
        console.log(this.name);
    }
}

對於this關鍵詞,即無論是該物件的哪個例項被建構函式建立,它的name屬性都是引數name的值,doSomething方法中使用的也是引數name。簡單理解就是用this指代了Person

建構函式通常首字母大寫,用於區分普通函式。

接下來,通過new關鍵詞,使用前面建立的建構函式(使用建構函式也叫例項化):

let leo = new Person("leo");
leo.name;    // "leo"

let pingan = new Person("pingan");
pingan.name; // "pingan"

然後一個簡單的建構函式就寫好了,通常在開發的時候,可能會有很多的引數:

function Man(name, age, height, weight){
    this.name = name;
    this.age = age + `歲`;
    this.HeightAndWeight = {
        height,
        weight
    };
    this.doSomething = function (){
        console.log(`
            ${this.name}: height:${this.HeightAndWeight.height}m, 
            weight:${this.HeightAndWeight.weight}Kg!!`
        );
    };
}

let leo = new Man("leo",25,1.8,68);
leo.doSomething();  // leo: height:1.8m, weight:68Kg!!

3.JS中的原型

3.1理解原型

這裡需要先了解一下ObjectFunction,這兩個函式都是JS的自帶函式,Object繼承自己,Function繼承自己,相互繼承對方,即ObjectFunction既是函式也是物件。

console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true

ObjectFunction的例項,而Function是它自己的例項。

console.log(Function.prototype); // ƒ () { [native code] }
console.log(Object.prototype);  // Object

另外,只有通過Function建立的函式都是函式物件,其他都是普通物件(通常由Object建立):

function f1(){};
typeof f1 //"function"
 
 
var o1 = new f1();
typeof o1 //"object"
 
var o2 = {};
typeof o2 //"object"

理論知識:

JavaScript 常被描述為一種基於原型的語言 (prototype-based language)——每個物件擁有一個原型物件,物件以其原型為模板、從原型繼承方法和屬性。
原型物件也可能擁有原型,並從中繼承方法和屬性,一層一層、以此類推。這種關係常被稱為原型鏈 (prototype chain),它解釋了為何一個物件會擁有定義在其他物件中的屬性和方法。
準確地說,這些屬性和方法定義在Object的構造器函式(constructor functions)之上的prototype屬性上,而非物件例項本身。

個人理解:

  • JS中所有的函式物件,都有一個prototype屬性,對應當前物件的原型,但普通物件沒有,而prototype屬性下還有一個constructor,指向這個函式。
var p = {};
p.prototype;         // undefined
p instanceof Object; // true

function f (){}; 
f.prototype;         // object {constructor: ƒ}
f === f.prototype.constructor;           // true
Object === Object.prototype.constructor; // true
  • JS中所有的物件,都有一個_proto_屬性,指向例項物件的建構函式原型(由於_proto_是個非標準屬性,因此只有ffchrome兩個瀏覽器支援,標準方法是Object.getPrototypeOf())。
var p = new Person(); 
p._proto === Person.prototype;  //true

修改原型:
經常我們也需要對原型進行修改:

function Person (name){
    this.name = name;
}
// 新增一個getName方法
Person.prototype.getName = function(){
    return "名字:" + this.name;
}
var p = new Person("leo"); 
p.getName();   // "名字:leo"

這裡也說明了原型進行繼承,p繼承Person原型中新增的函式屬性getName

3.2原型鏈

概念:
javascript中,每個物件都會在內部生成一個 proto 屬性,當我們訪問一個物件屬性時,如果這個物件不存在就會去 proto 指向的物件裡面找,一層一層找下去,直到找到為止,如果到了原型鏈頂端,還沒找到,則返回undefined,這就是javascript原型鏈的概念。

原型鏈:

總結:

  • 除了Objectprototype的原型是null,所有物件和原型都有自己的原型,物件的原型指向原型物件。
  • JS中所有的東西都是物件,所有的東西都由Object衍生而來, 即所有東西原型鏈的終點指向null。

更加詳細的介紹,可以檢視下面參考文章。


參考文章:

1.MDN JavaScript 物件入門

2.基於js中的原型

本部分內容到這結束

系列目錄:

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 https://github.com/pingan8787…
JS小冊 js.pingan8787.com

歡迎關注微信公眾號【前端自習課】每天早晨,與您一起學習一篇優秀的前端技術博文 .

相關文章