成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JavaScript 中的面向對象

開發 前端
JavaScript 語言本身的設計缺陷,誤打誤撞,成了解釋最為徹底的“世界原本的樣子”的計算機編程語言;

[[430327]]

本文轉載自微信公眾號「勾勾的前端世界」,作者西嶺。轉載本文請聯系勾勾的前端世界公眾號。

回憶一下什么是對象:Coding 第一奧義:面向對象編程

JavaScript 語言本身的設計缺陷,誤打誤撞,成了解釋最為徹底的“世界原本的樣子”的計算機編程語言;

——西嶺《凡人凡語》

Everything is object (萬物皆對象),JS 語言中將一切都視為 對象 。

JavaScript 語言的對象體系,不基于“類” 創建對象,是基于構造函數(constructor)和原型鏈(prototype)。

簡單方式創建對象

我們可以直接通過 new Object() 創建:

  1. var person = new Object() 
  2. person.name = 'Jack' 
  3. person.age = 18 
  4.  
  5. person.sayName = function () { 
  6.     console.log(this.name

字面量方式創建對象

每次創建通過 new Object() 比較麻煩,所以可以通過它的簡寫形式對象字面量來創建:

  1. var person = { 
  2.   name'Jack'
  3.   age: 18, 
  4.   sayName: function () { 
  5.     console.log(this.name
  6.   } 

構造函數

JavaScript 語言使用構造函數作為對象的模板。

所謂 "構造函數",就是一個普通的函數,只不過我們專門用它來生成對象,這樣使用的函數,就是構造函數。

它提供模板,描述對象的基本結構。一個構造函數,可以生成多個對象,這些對象都有相同的結構。

  1. function Person (name, age) { 
  2.   this.name = name 
  3.   this.age = age 
  4.   this.sayName = function () { 
  5.     console.log(this.name
  6.   } 
  7.  
  8. var p1 = new Person('Jack', 18) 
  9. p1.sayName() // => Jack 
  10.  
  11. var p2 = new Person('Mike', 23) 
  12. p2.sayName() // => Mike 

解析構造函數代碼的執行

在上面的示例中,使用 new 操作符創建 Person 實例對象;

以這種方式調用構造函數會經歷以下 5 個步驟:

  • 創建一個空對象,作為將要返回的對象實例。
  • 將這個空對象的原型,指向構造函數的prototype屬性。先記住,后面講
  • 將這個空對象賦值給函數內部的this關鍵字。
  • 執行構造函數內部的代碼。
  • 返回新對象 (this)
  1. function Person (name, age) { 
  2.   // 當使用 new 操作符調用 Person() 的時候,實際上這里會先創建一個對象 
  3.   // 然后讓內部的 this 指向新創建的對象 
  4.   // 接下來所有針對 this 的操作實際上操作的就是剛創建的這個對象 
  5.  
  6.   this.name = name 
  7.   this.age = age 
  8.   this.sayName = function () { 
  9.     console.log(this.name
  10.   } 
  11.  
  12.   // 在函數的結尾處會將 this 返回,也就是這個新對象 

構造函數和實例對象的關系

構造函數是根據具體的事物抽象出來的抽象模板,實例對象是根據抽象的構造函數模板得到的具體實例對象。

實例對象由構造函數而來,一個構造函數可以生成很多具體的實例對象,而每個實例對象都是獨一無二的。

每個對象都有一個 constructor 屬性,該屬性指向創建該實例的構造函數。

反推出來,每一個對象都有其構造函數

  1. console.log(p1.constructor === Person) // => true 
  2. console.log(p2.constructor === Person) // => true 
  3. console.log(p1.constructor === p2.constructor) // => true 

因此,我們可以通過實例對象的 constructor 屬性判斷實例和構造函數之間的關系。

構造函數存在的問題

以構造函數為模板,創建對象,對象的屬性和方法都可以在構造函數內部定義。

  1. function Cat(name, color) { 
  2.   this.name = name
  3.   this.color = color; 
  4.   this.say = function () { 
  5.     console.log('hello'+this.name,this.color); 
  6.   }; 
  7. var cat1 = new Cat('貓''白色');  
  8. var cat2 = new Cat('貓''黑色');  
  9. cat1.say(); 
  10. cat2.say(); 

在該示例中,從表面上看好像沒什么問題,但是實際上這樣做,有一個很大的弊端。那就是對于每一個實例對象, name 和 say 都是一模一樣的內容,每一次生成一個實例,都必須為重復的內容,多占用一些內存,如果實例對象很多,會造成極大的內存浪費。

那么,能不能將相同的內容,放到公共部分,節約計算機資源呢?

原型

JavaScript 的每個對象都會繼承一個父級對象,父級對象稱為 原型 (prototype) 對象。

原型也是一個對象,原型對象上的所有屬性和方法,都能被子對象 (派生對象) 共享,通過構造函數生成實例對象時,會自動為實例對象分配原型對象。而每一個構造函數都有一個prototype屬性,這個屬性就是實例對象的原型對象。

null 沒有自己的原型對象。

這也就意味著,我們可以把所有對象實例需要共享的屬性和方法直接定義在構造函數的 prototype 屬性上,也就是實例對象的原型對象上。

  1. function Cat(color) { 
  2.   this.color = color; 
  3.  
  4. Cat.prototype.name = "貓"
  5. Cat.prototype.sayhello = function(){ 
  6.     console.log('hello'+this.name,this.color); 
  7. Cat.prototype.saycolor = function (){ 
  8.     console.log('hello'+this.color); 
  9.  
  10. var cat1 = new Cat('白色');  
  11. var cat2 = new Cat('黑色');  
  12. cat1.sayhello(); 
  13. cat2.saycolor(); 

這時所有實例對象的 name 屬性和 sayhello() 、saycolor 方法,其實都是在同一個內存地址的對象中,也就是構造函數的 prototype 屬性上,因此就提高了運行效率節省了內存空間。

原型及原型鏈

構造函數的 prototyp 屬性,就是由這個構造函數 new 出來的所有實例對象的 原型對象

所有對象都有原型對象。

  1. function Cat(name, color) { 
  2.     this.name = name
  3.  } 
  4.  
  5. var cat1 = new Cat('貓'); 
  6.  
  7. console.log(cat1.__proto__.__proto__.__proto__); 

而原型對象中的屬性和方法,都可以被實例對象直接使用。

每當代碼讀取某個對象的某個屬性時,都會執行一次搜索,目標是具有給定名字的屬性。

  • 搜索首先從對象實例本身開始
  • 如果在實例中找到了具有給定名字的屬性,則返回該屬性的值
  • 如果沒有找到,則繼續搜索指針指向的原型對象,在原型對象中查找具有給定名字的屬性
  • 如果在原型對象中找到了這個屬性,則返回該屬性的值
  • 如果還是找不到,就到原型的原型去找,依次類推。
  • 如果直到最頂層的Object.prototype還是找不到,則返回undefined。

而這正是多個對象實例共享原型所保存的屬性和方法的基本原理。

對象的屬性和方法,有可能是定義在自身內,也有可能是定義在它的原型對象上。由于原型本身也是對象,又有自己的原型,所以形成了一條可向上追溯的鏈條,叫 原型鏈(prototype chain)。

注意,不在要原型上形成多層鏈式查找,非常浪費資源。

內置標準庫與包裝對象

在內置標準對象中,對象是 JavaScript 語言最主要的數據類型,三種原始類型的值——數值、字符串、布爾值——在一定條件下,也會自動轉為對象,也就是原始類型的“包裝對象”(wrapper)。

所謂“包裝對象”,就是分別與數值、字符串、布爾值相對應的Number、String、Boolean三個原生對象。這三個原生對象可以把原始類型的值變成(包裝成)對象。

  1. var v1 = new Number(123); 
  2. var v2 = new String('abc'); 
  3. var v3 = new Boolean(true); 
  4.  
  5. typeof v1 // "object" 
  6. typeof v2 // "object" 
  7. typeof v3 // "object" 
  8.  
  9. v1 === 123 // false 
  10. v2 === 'abc' // false 
  11. v3 === true // false 

包裝對象的最大目的,首先是使得 JavaScript 的對象涵蓋所有的值,其次使得原始類型的值可以方便地調用某些方法。

原始類型的值,可以自動當作對象調用,即調用各種對象的方法和參數。

這時,JavaScript 引擎會自動將原始類型的值轉為包裝對象實例,在使用后立刻銷毀實例。

比如,字符串可以調用length屬性,返回字符串的長度。

  1. 'abc'.length // 3 

上面代碼中,abc是一個字符串,本身不是對象,不能調用length屬性。JavaScript 引擎自動將其轉為包裝對象,在這個對象上調用length屬性。調用結束后,這個臨時對象就會被銷毀。這就叫原始類型與實例對象的自動轉換。

 

責任編輯:武曉燕 來源: 勾勾的前端世界
相關推薦

2009-06-10 22:06:29

JavaScript面向對象

2012-01-17 09:34:52

JavaScript

2017-04-21 09:07:39

JavaScript對象編程

2018-12-19 19:30:46

JavaScript創建對象前端

2012-02-27 09:30:22

JavaScript

2012-12-25 10:51:39

IBMdW

2011-05-25 11:15:02

Javascript繼承

2011-05-13 11:05:52

javascript

2011-05-25 10:21:44

Javascript

2011-05-13 09:58:46

javascript

2011-05-13 10:51:25

javascript

2011-05-13 11:17:18

javascript

2011-05-13 11:27:59

javascript

2011-05-25 10:59:26

Javascript繼承

2011-05-13 12:38:58

javascript

2012-03-13 16:39:52

Java

2009-07-14 16:51:50

Jython中的對象

2011-06-28 14:11:33

JavaScript

2022-08-15 15:39:23

JavaScript面向對象數據

2010-10-08 09:13:15

oop模式JavaScript
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天天天天天天干 | 国产精品国产三级国产aⅴ无密码 | 日韩精品成人 | 久久噜| 日本一区二区不卡 | 欧美啪啪 | 日韩在线播放av | 一区二区三区久久久 | 中文字幕一页二页 | 九九热在线视频免费观看 | 成人精品一区二区三区四区 | 日本精品久久久久久久 | 精品中文字幕在线观看 | 一区二区在线免费观看 | 99精品亚洲国产精品久久不卡 | 久久91 | 欧美一区二区三区视频 | 午夜精品久久久久久久久久久久久 | 国产精品毛片一区二区在线看 | 综合久久色 | 成年视频在线观看 | 久久国产精品久久国产精品 | 国产伦精品一区二区三区视频金莲 | 亚洲欧美成人影院 | 特级丰满少妇一级aaaa爱毛片 | 亚洲精品在线播放 | 美女一级毛片 | 九九久久免费视频 | 亚洲一区 中文字幕 | 在线视频国产一区 | 中文字幕在线欧美 | 国产精品久久久久久久久免费桃花 | 国产午夜一级 | 欧美国产视频一区二区 | 一区亚洲 | 一区二区在线免费观看视频 | 精品网 | 黄色大片在线视频 | 午夜视频在线 | 日韩精品一区二区三区四区视频 | 国产综合精品一区二区三区 |