1. 程式人生 > >javaScript 面向物件--封裝和prototype屬性

javaScript 面向物件--封裝和prototype屬性

一般面向物件的語言都具有三大特徵,封裝、繼承,多型,例如像java 和c++。但是javaScript它可以說不是完全的面向物件的語言,因為它沒有類的概念,但是它又是面向物件的,因為它可以封裝屬性和方法,並且也可以實現繼承。

1、字面量模式

字面量的模式來建立一個物件

var person = {
    name : 'wzj',
    age : 25
}

console.log(person.name);// wzj
console.log(typeof person);//Object 

但是這種方式比較麻煩,如果生成多個例項,寫起來比較繁瑣。

2、通過函式模式

可以通過函式來解決上面程式碼重複的問題

function person(name, age){
    var person = new Object();
    person.name = name;
    person.age = age;
    return person;
}

var person1 = person('wzj',25);//會返回一個物件
var person2 = person('dxy',22);//也會返回一個物件
console.log(person.name);//wzj

可以看出二者並沒有必然的聯絡,不能反映他們是同一個 person 創建出來的。
這裡寫圖片描述
我們通過控制檯可以看到,這兩個物件不僅具有age和name屬性還有一個 proto

屬性,這個是物件的原型鏈,由於我們是直接通過在函式中例項化Object建構函式,所以此時這兩個物件的原型鏈的constructor屬性丟指向Object()函式,並且繼承了Object()的所有方法.
這裡寫圖片描述

3、通過建構函式封裝屬性和方法

建構函式的概念我們並不陌生,在java中建構函式是用來實現物件屬性的初始化的,並且建構函式也可以實現過載。但是在javaScript中的建構函式和一般的函式沒有多大區別。
javaScript中的建構函式大致具有以下特徵:

  1. 建構函式就是一個普通的函式,但是首字母要大寫例如 Person(name, age)
  2. 建構函式內部具有this,變數,並且this會繫結在例項物件上。
  3. 建構函式需要通過new 關鍵字來例項化物件,並且通過new關鍵字建立的物件都具有constructor屬性。
function Person(name, age){
    this.name = name;
    this.age = age;
    this.sayName = function () {
        console.log(this.name);
    }
}

var person1 = new Person('wzj',25);
var person2 = new Person('dxy',23);

//二者指向同一個建構函式,返回true
console.log(person1.constructor == person2.constructor);
//可以判斷出例項物件和原型物件之間的關係,返回true
console.log(person1 instanceof Person);

這裡寫圖片描述
通過建構函式的方法建立物件不僅消除那種字面量冗餘的問題,也解決了原型物件和例項物件之間的關聯問題,但是建構函式也具有一些問題,例如方法和屬性的共有部分如何抽取問題,在java中我們可以宣告介面來實現共有方法的抽取,那麼在javaScript中我們如何實現呢?

4、建構函式的一些問題

首先來看一個示例:

function Car(name, color){
      this.name = name;
      this.color = color;
      this.sayName = function () {
          console.log(this.name);
      }

      this.material = '金屬';
      this.start = function () {
          console.log("啟動引擎!")
      }
  }

  var car1 = new Car('梅賽德斯',"黑色");
  var car2 = new Car('凱迪拉克','白色');

  //這個方法每個物件都具有
  car1.start();
  car2.start();
  //返回false,因為所有的例項的這個方法 都是存在一個自己獨立的地址中
  console.log(car1.start == car2.start);

然後在看下控制檯
這裡寫圖片描述
可以看到兩個物件有公共的部分,這種方式造成了記憶體的浪費,因為這兩個對像所共有的方法,是在各自的記憶體中存放著,並不是存在公共的區域,那麼我們能不能實現java中樣把這種共有的方法,宣告為static的放在類載入區呢,很顯然不能,因為javaScript沒有類的概念的。
並且,瀏覽沒有類載入區的概念,所以我們不能借鑑。但是並不是說不能實現那種方式。
javaScript規定 每個建構函式都預設具有prototype屬性,並且這個屬性指向一個物件,這個被指向的物件的所有屬性和方法都將被次建構函式所繼承。

function Car2(name, color){
     this.name = name;
     this.color = color;
     this.sayName = function () {
         console.log(this.name);
     }
 }

 //通過 prototype 來實現共有方法的抽取,並且實現了物件方法的繼承
 Car2.prototype.start = function () {
     console.log("引擎啟動!")
 }
 Car2.prototype.material = '金屬';

 /**
 1. 此時所有的例項的start方法和material屬性,其實都指向同一個記憶體地址,即 指向prototype物件.
 2. @type {Car2}
  */
 var car1 = new Car2('梅賽德斯','黑色');
 var car2 = new Car2('凱迪拉克','白色');

 car1.start();
 car2.start();
 console.log(car1.start == car2.start);//返回true,因為所有例項的方法都指向同一個地址

通過控制檯可以發現,car1和car2自身並沒有start()方法和material屬性,但是可以呼叫start方法。
這裡寫圖片描述
通過原型鏈可以看到,start()方法和material屬性 存在。因此可以通過建構函式的prototype屬性來實現方法和屬性的共有和擴充套件。

5、驗證prototype的一般方法
  • 1、isPrototypeOf(): 用來判斷,某個prototype物件和某個例項之間的關係.
  • 2、hasOwnPrototype(): 用來判斷,某個屬性是例項自身的屬性還是繼承自Prototype物件的屬性.
  • 3、in: 用來判斷某個例項是否含有某個屬性,不管是否是自身屬性,還可以用來遍歷某個物件的 所有屬性。
    這些方法是繼承自Object()物件.
console.log(Car2.prototype.isPrototypeOf(car1));//true
console.log(car1.hasOwnProperty('start'));//false start是 prototype物件的屬性
console.log(car1.hasOwnProperty('name')); //true name是car1自身的屬性

console.log('start' in car1);//true
console.log('name' in car1); //true
console.log('age' in car1);  //false
console.log('-------------------------\n')
for (var prop in car1){
      console.log("car1["+prop+"] = "+car1[prop]);
}

控制檯列印結果
這裡寫圖片描述

5、prototype的使用

知道了prototype的作用,name應該怎麼使用它呢?如果通過原型新增得方法和物件自身所具有的方法和屬性重複了,會優先呼叫哪一個方法?

function Car2(name, color){
    this.name = name;
    this.color = color;
    this.sayName = function () {
        console.log(this.name);
    }
}

//通過 prototype 來實現共有方法的抽取,並且實現了物件方法的繼承
Car2.prototype.start = function () {
    console.log("引擎啟動!")
}
Car2.prototype.material = '金屬';

Car2.prototype.name = "default";
Car2.prototype.sayName = function () {
    console.log(this.name+"覆蓋建構函式中已經具有的方法!")
}

var car = new Car2('梅賽德斯','黑色');
car.sayName();//列印梅賽德斯
console.log(car.name);//列印梅賽德斯
console.log(car.material);//列印黑色

通過控制檯可以發現,物件本身所具有的的方法,並沒有被通過建構函式建立的方法所覆蓋
這裡寫圖片描述

得出以下結論

當物件本身的屬性或方法與原型的屬性和方法同名的時候

  • 預設呼叫的物件自身的屬性和方法
  • 通過原型增加的屬性和方法是確實存在的
  • 函式本身的屬性和方法要優先於原型的屬性和方法

當通過delete方法刪除物件中的方法的時候不會刪除建構函式中的.

var car = new Car2('梅賽德斯','黑色');
Car2.prototype.name = "default";
Car2.prototype.sayName = function () {
    console.log(this.name+"覆蓋建構函式中已經具有的方法!")
}
//刪除物件car 中的方法sayName(),此時物件本身並不具有這個方法
delete (car.sayName);

car.sayName();//列印default覆蓋建構函式中已經具有的方法!
console.log(car.name);//列印default
console.log(car.material);//列印黑色

這裡寫圖片描述

相關推薦

javaScript 面向物件--封裝prototype屬性

一般面向物件的語言都具有三大特徵,封裝、繼承,多型,例如像java 和c++。但是javaScript它可以說不是完全的面向物件的語言,因為它沒有類的概念,但是它又是面向物件的,因為它可以封裝屬性和方法,並且也可以實現繼承。 1、字面量模式 字面量的模式

Java面向物件封裝繼承

面向物件 什麼是面向過程、面向物件? 面向過程與面向物件都是我們程式設計中,編寫程式的一種思維方式。   面向過程的程式設計方式,是遇到一件事時,思考“我該怎麼做”,然後一步步實現的過程。例如:公司打掃衛生(擦玻璃、掃地、拖地、倒垃圾等),按照面向過程的程式設計方式會思考“打掃衛生我該怎麼做,然後一件件的完

javascript面向物件程式設計--設計超類子類,設計元類

在javascript中,Object物件是通用類,其他所有內建物件和自定義構造物件都是專用類,即Object物件是超類,其他內建物件和自定義物件都是Object的子類,所有在javascript語言中,所有的物件都繼承Object定義的屬性和方法 Object.prototype.name='

JavaScript 面向物件之二 —— 函式上下文(call() apply())

本系列文章根據《愛前端邵山歡老師深入淺出的js面向物件》視訊整理歸納 call() 和 apply() 這兩個都是函式的方法,只有函式能夠通過點方法呼叫call()、apply(),表示用指定的上下文執行這個函式。 如下,定義一個函式 fun,當 fun 函式裡

JavaScript面向物件程式設計-封裝

前言 面向物件程式設計是將需求抽象成一個物件,針對物件分析其特徵(屬性)和動作(方法)。這個物件我們稱之為類。面向物件程式設計思想其中一個特點就是封裝,就是把需要的功能放在一個物件裡。但是JavaScript這種解釋性的弱型別語言沒有經典強型別語言中通過關鍵字cla

javascript面向物件程式設計--繼承--類繼承2(封裝類繼承模式)

function extend(Sub,Sup){     var F=function(){};   F.prototype=Sup.prototype;   Sub.prototype=new F();  Sub.prototype.constructor=Sub

javascript面向物件程式設計---封裝--被動封裝+主動封裝

封裝:把物件內部的資料和操作細節進行隱藏,javascript不支援封裝操作,但可以使用閉包函式來模擬型別封裝 被動封裝:對物件內部資料進行適當約定,這種約定並沒有強制性,它主要針對公共物件而言 var Card=function(name,sex,work,detail

Javascript 面向物件程式設計(一):封裝

Javascript是一種基於物件(object-based)的語言,你遇到的所有東西幾乎都是物件。但是,它又不是一種真正的面向物件程式設計(OOP)語言,因為它的語法中沒有class(類)。 那麼,如果我們要把"屬性"(property)和"方法"(method),封裝成

Javascript 面向物件程式設計封裝問題

//建構函式模式相對於工廠模式來說,比較省記憶體。 //下面的方法是建構函式模式加上原型模式實現,建構函式模式雖說比工廠模式省記憶體, //但是還是存在浪費記憶體的現象。 function Person(name,age,job){     this.name=name;

javascript面向物件系列第一篇——建構函式原型物件

前面的話   一般地,javascript使用建構函式和原型物件來進行面向物件程式設計,它們的表現與其他面向物件程式語言中的類相似又不同。本文將詳細介紹如何用建構函式和原型物件來建立物件 建構函式   建構函式是用new建立物件時呼叫的函式,與普通唯一的區別是建構函式名應該首字母大寫 func

讀《JavaScript 面向物件精要》JavaScript 啟示錄》精華總結

導讀:本文詳細總結了JavaScript 面向物件基礎的知識點,主要來自《JavaScript 面向物件精要》《JavaScript 啟示錄》這兩本書,推薦給各位做做開發的朋友。 目錄 引子: 最近看了兩本書,書中有些內容對自己還是很新的

Python.面向物件---類物件屬性的增刪改查

一,類屬性的操作class Chinese: country = 'China' def __init__(self,name): self.name = name def play_ball(self,ball): p

自學Python day6--------面向物件程式設計(例項屬性屬性

因為Python是動態語言,可以根據例項任意繫結屬性,如: class Student(object): def __init__(self, name): self.name = name s = Student('Bob') s.

JavaScript(面向物件+原型理解+繼承+作用域鏈閉包+this使用總結)

JavaScript(面向物件+原型理解+繼承+作用域鏈和閉包+this使用總結) 一、面向物件 1、什麼是面向物件 ☞ 面向物件就是把構成問題事物分解成多個物件,建立物件不是為了

javascript 面向物件屬性型別)-筆記

 屬性型別:   屬性在建立時都帶一些特徵值,javascript通過這些特殊值定義他們行為,javascript中有兩種屬性:資料屬性,           訪問器屬性   1.資料屬性   資料屬性包含一個數據的值的位置。在這個位

黑馬程式設計師--Java學習日記之面向物件(封裝,繼承構造方法)

------- android培訓、java培訓、期待與您交流! ---------- 面向物件思想:     面向過程,以函式為基礎,關注的是實現過程;     面向物件,以物件為基礎,關注的是最終結果; 面向物件思想特點         是一種更符合我們思想習慣的思想

Python 進階_OOP 面向物件程式設計_類屬性方法

目錄 類屬性 在理解類屬性之前要先搞清楚 例項屬性 和 函式屬性 之間的區別: 1. 例項屬性:指的是例項化類物件的屬性,需要在類中使用 self 關鍵字來將其和例項化物件繫結的屬性。 2. 函式屬性:指的是定義在函式體內的屬性,其可以是例項屬

javascript 面向物件學習(三)——this,bind、apply call

this 是 js 裡繞不開的話題,也是非常容易混淆的概念,今天試著把它理一理。 this 在非嚴格模式下,總是指向一個物件,在嚴格模式下可以是任意值,本文僅考慮非嚴格模式。記住它總是指向一個物件對於理解它的意義很重要。this 在實際使用中,大致分為以下幾種情況: 1. 函式作為物件的方法呼叫時,this

javascript面向對象原型————呱呱二號

無法訪問 原型模式 冒充 判斷 傳遞 pre asp clas 相等 面向對象 1、工廠模式 function createObject(name,age){ let obj = new Object(); this.name = name; this.age

javascript 面向對象繼承

color asc asdasdas java 代碼 round == ima 個人 我相信,當你讀完這篇100%原創文章時,javascript 面向對象和繼承輕松拿下不再是問題。 統一的html和css <div id="app"></