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

再談JavaScript面向對象編程

開發 前端
雖有陳皓《Javascript 面向對象編程》珠玉在前,但是我還是忍不住再畫蛇添足的補上一篇文章,主要是因為javascript這門語言魅力。另外這篇文章是一篇入門文章。

雖有陳皓《Javascript 面向對象編程》珠玉在前,但是我還是忍不住再畫蛇添足的補上一篇文章,主要是因為javascript這門語言魅力。另外這篇文章是一篇入門文章,我也是才開始學習Javascript,有一點心得,才想寫一篇這樣文章,文章中難免有錯誤的地方,還請各位不吝吐槽指正

51CTO推薦專題:JavaScript入門

吐槽Javascript

初次接觸Javascript,這門語言的確會讓很多正規軍感到諸多的不適,這種不適來自于Javascript的語法的簡練和不嚴謹,這種不適也來自Javascript這個悲催的名稱,我在想網景公司的Javascript設計者在給他起名稱那天一定是腦殼進水了,讓Javascript這么多年來受了這么多不白之冤,人們都認為他是Java的附屬物,一個WEB玩具語言。因此才會有些人會對Javascript不屑,認為Javascript不是一門真正的語言,但是這此他們真的錯了。Javascript不僅是一門語言,是一門真真正正的語言,而且他還是一門里程碑式的語言,他***多種新的編程模式原型繼承,閉包,對后來的動態語言產生了巨大的影響。做為當今***的語言(沒有之一),看看git上提交的最多的語言類型就能明白。隨著HTML5的登場,瀏覽器將在個人電腦上將大顯身手,完全有替換OS的趨勢的時候,Javascript做為瀏覽器上的一門唯一真真的語言,如同C之于 unix/linux,java之于JVM,Cobol之于MainFrame,我們也需要來重新的認真地認識和審視這門語言。另外Javascript的正式名稱是:ECMAScript,這個名字明顯比Javascript帥太多了!

言歸正傳,我們切入主題——Javascript的面向對象編程。要談Javascript的面向對象編程,我們***步要做的事情就是忘記我們所學的面向對象編程。傳統C++或Java的面向對象思維來學習Javascript的面向對象會給你帶來不少困惑,讓我們先忘記我們所學的,從新開始學習這門特殊的面向對象編程。既然是OO編程,要如何來理解OO編程呢,記得以前學C++,學了很久都不入門,后來有幸讀了《Inside The C++ Object Model》這本大作,頓時豁然開朗,因此本文也將以對象模型的方式來探討的Javascript的OO編程。因為Javascript 對象模型的特殊性,所以使得Javascript的繼承和傳統的繼承非常不一樣,同時也因為Javascript里面沒有類,這意味著Javascript里面沒有extends,implements。那么Javascript到底是如何來實現OO編程的呢?好吧,讓我們開始吧,一起在Javascript的OO世界里來一次漫游

首先,我們需要先看看Javascript如何定義一個對象。下面是我們的一個對象定義:

  1. var o = {}; 

還可以這樣定義一個對象

  1. function f() {  

對,你們沒有看錯,在Javascript里面,函數也是對象。

當然還可以

  1. var array1= [ 1,2,3]; 

數組也是一個對象。

其他關于對象的基本的概念的描述,還是請各位親們參見陳皓《Javascript 面向對象編程》文章。

對象都有了,唯一沒有的就是class,因為在Javascript里面是沒有class關鍵字的,算好還有function,function的存在讓我們可以變通的定義類,在擴展這個主題前,我們還需要了解一個Javascript對象最重要的屬性,__proto__成員。

__proto__成員

嚴格的說這個成員不應該叫這個名字,__proto__是Firefox中的稱呼,__proto__只有在Firefox瀏覽器中才能被訪問到。做為一個對象,當你訪問其中的一個成員或方法的時候,如果這個對象中沒有這個方法或成員,那么Javascript引擎將會訪問這個對象的__proto__成員所指向的另外的一個對象,并在那個對象中查找指定的方法或成員,如果不能找到,那就會繼續通過那個對象的__proto__成員指向的對象進行遞歸查找,直到這個鏈表結束。

好了,讓我們舉一個例子。

比如上上面定義的數組對象array1。當我們創建出array1這個對象的時候,array1實際在Javascript引擎中的對象模型如下:

 

 

array1對象具有一個length屬性值為3,但是我們可以通過如下的方法來為array1增加元素:

  1. array1.push(4); 

push這個方法來自于array1的__proto__成員指向對象的一個方法(Array.prototye.push())。正是因為所有的數組對象(通過[]來創建的)都包含有一個指向同一個具有push,reverse等方法對象(Array.prototype)的__proto__成員,才使得這些數組對象可以使用push,reverse等方法。

那么這個__proto__這個屬性就相當于面向對象中的”has a”關系,這樣的的話,只要我們有一個模板對象比如Array.prototype這個對象,然后把其他的對象__proto__屬性指向這個對象的話就完成了一種繼承的模式。不錯!我們完全可以這么干。但是別高興的太早,這個屬性只在FireFox中有效,其他的瀏覽器雖然也有屬性,但是不能通過__proto__來訪問,只能通過getPrototypeOf方法進行訪問,而且這個屬性是只讀的??磥砦覀円贘avascript實現繼承并不是很容易的事情啊。

函數對象prototype成員

首先我們先來看一段函數prototype成員的定義,

When a function object is created, it is given a prototype member which is an object containing a constructor member which is a reference to the function object

當一個函數對象被創建時,這個函數對象就具有一個prototype成員,這個成員是一個對象,這個對象包含了一個構造子成員,這個構造子成員會指向這個函數對象。

例如:

  1. function Base() {  
  2.     this.id = "base" 

Base這個函數對象就具有一個prototype成員,關于構造子其實Base函數對象自身,為什么我們將這類函數稱為構造子呢?原因是因為這類函數設計來和new 操作符一起使用的。為了和一般的函數對象有所區別,這類函數的首字母一般都大寫。構造子的主要作用就是來創建一類相似的對象。

上面這段代碼在Javascript引擎的對象模型是這樣的

 

 

new 操作符

在有上面的基礎概念的介紹之后,在加上new操作符,我們就能完成傳統面向對象的class + new的方式創建對象,在Javascript中,我們將這類方式成為Pseudoclassical。

基于上面的例子,我們執行如下代碼

  1. var obj = new Base(); 

這樣代碼的結果是什么,我們在Javascript引擎中看到的對象模型是:

 

 

new操作符具體干了什么呢?其實很簡單,就干了三件事情。

  1. var obj  = {};  
  2. obj.__proto__ = Base.prototype;  
  3. Base.call(obj); 

***行,我們創建了一個空對象obj

第二行,我們將這個空對象的__proto__成員指向了Base函數對象prototype成員對象

第三行,我們將Base函數對象的this指針替換成obj,然后再調用Base函數,于是我們就給obj對象賦值了一個id成員變量,這個成員變量的值是”base”,關于call函數的用法,請參看陳皓《Javascript 面向對象編程》文章

如果我們給Base.prototype的對象添加一些函數會有什么效果呢?

例如代碼如下:

  1. Base.prototype.toString = function() {  
  2.     return this.id;  

那么當我們使用new創建一個新對象的時候,根據__proto__的特性,toString這個方法也可以做新對象的方法被訪問到。于是我們看到了:

構造子中,我們來設置‘類’的成員變量(例如:例子中的id),構造子對象prototype中我們來設置‘類’的公共方法。于是通過函數對象和Javascript特有的__proto__與prototype成員及new操作符,模擬出類和類實例化的效果。

Pseudoclassical 繼承

我們模擬類,那么繼承又該怎么做呢?其實很簡單,我們只要將構造子的prototype指向父類即可。例如我們設計一個Derive 類。如下

  1. function Derive(id) {  
  2.     this.id = id;  
  3. }  
  4. Derive.prototype = new Base();  
  5. Derive.prototype.test = function(id){  
  6.     return this.id === id;  
  7. }  
  8. var newnewObj = new Derive("derive"); 

這段代碼執行后的對象模型又是怎么樣的呢?根據之前的推導,應該是如下的對象模型

 

 

這樣我們的newObj也繼承了基類Base的toString方法,并且具有自身的成員id。關于這個對象模型是如何被推導出來的就留給各位同學了,參照前面的描述,推導這個對象模型應該不難。

Pseudoclassical繼承會讓學過C++/Java的同學略微的感受到一點舒服,特別是new關鍵字,看到都特親切,不過兩者雖然相似,但是機理完全不同。當然不關什么樣繼承都是不能離不開__proto__成員的。

Prototypal繼承

這是Javascript的另外一種繼承方式,這個繼承也就是之前陳皓文章《Javascript 面向對象編程》中create函數,非??上У氖沁@個是ECMAScript V5的標準,支持V5的瀏覽器目前看來也就是IE9,Chrome***版本和Firefox。雖然看著多,但是做為IE6的重災區的中國,我建議各位還是避免使用create函數。好在沒有create函數之前,Javascript的使用者已經設計出了等同于這個函數的。例如:我們看看Douglas Crockford的object函數。

  1. function object(old) {  
  2.    function F() {};  
  3.    F.prototype = old;  
  4.    return new F();  
  5. }  
  6. var newObj = object(oldObject); 

例如如下代碼段

  1. var base ={  
  2.   id:"base",  
  3.   toString:function(){  
  4.           return this.id;  
  5.   }  
  6. };  
  7. var derive = object(base); 

上面函數的執行后的對象模型是:

 

 

如何形成這樣的對象模型,原理也很簡單,只要把object這個函數擴展一下,就能畫出這個模型,怎么畫留給讀者自己去畫吧。

這樣的繼承方式被稱為原型繼承。相對來說要比Pseudoclassical繼承來的簡單方便。ECMAScript V5正是因為這原因也才增加create函數,讓開發者可以快速的實現原型繼承。

上述兩種繼承方式是Javascript中最常用的繼承方式。通過本文的講解,你應該對Javascript的OO編程有了一些‘原理’級的了解了吧

參考:

《Prototypes and Inheritance in JavaScript Prototypes and Inheritance in JavaScript》

Advance Javascript (Douglas Crockford 大神的視頻,一定要看啊)

題外話:

web2.0后,web應用可謂飛速發展,如今在HTML5發布之際,瀏覽器的功能被大大強化,我感覺Browser遠遠在不是一個Browser那么簡單了。記得C++之父曾經這樣說過JAVA,JAVA不是跨平臺,JAVA本身就是一個平臺。如今的Browser也本身就是一個平臺了,好在這個平臺是基于標準的。如果Browser是平臺,由于Browser安全沙箱的限制,個人電腦的資源被使用的很少,感覺Browser就是一個NC(Network Computer)?我們居然又回到了Sun最初提出的構想,Sun是不是太強大了些?

原文:http://coolshell.cn/articles/6668.html

【編輯推薦】

  1. JavaScript面向對象編程深入分析
  2. JavaScript組件模式深入淺出
  3. JavaScript繼承詳解
  4. JavaScript面向對象編程
  5. JavaScript中的陷阱大集合
責任編輯:陳貽新 來源: 酷殼
相關推薦

2012-01-17 09:34:52

JavaScript

2017-04-21 09:07:39

JavaScript對象編程

2011-05-25 10:21:44

Javascript

2011-05-25 10:59:26

Javascript繼承

2010-10-08 09:13:15

oop模式JavaScript

2011-06-28 14:11:33

JavaScript

2011-05-25 11:15:02

Javascript繼承

2010-11-17 11:31:22

Scala基礎面向對象Scala

2023-02-22 18:06:35

函數javascript面向對象編程

2019-11-18 17:05:02

JavaScript面向對象程序編程Java

2022-07-30 23:41:53

面向過程面向對象面向協議編程

2012-12-13 11:01:42

IBMdW

2021-10-21 18:47:37

JavaScript面向對象

2019-03-26 10:50:22

Python面向對象編程語言

2023-01-10 09:06:17

2010-07-16 17:23:57

Perl面向對象編程

2011-06-28 11:06:16

Scala

2012-12-18 09:24:47

2010-07-13 17:18:29

Perl面向對象編程

2023-12-11 15:32:30

面向對象編程OOPpython
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品观看 | 日韩精品一区二区三区中文字幕 | 91精品国产综合久久久久久 | 91久久| 亚洲视频区 | 亚洲最新在线视频 | 99久久精品免费看国产免费软件 | 欧美一级淫片007 | 免费a网| 精品国产欧美 | 一级欧美一级日韩片免费观看 | 伊人久久综合 | 亚洲精品国产第一综合99久久 | 久操福利| 国产1区 | 日日草夜夜草 | 久草福利 | 亚洲精品免费在线 | 国产福利免费视频 | 国产成人综合在线 | 日韩二 | 91精品久久久久久久久 | 九九热这里只有精品在线观看 | 色综合一区 | 一区二区国产精品 | 久久精品日产第一区二区三区 | 精品视频导航 | 国产精品爱久久久久久久 | 81精品国产乱码久久久久久 | 日本三级全黄三级三级三级口周 | 天天操网 | 日韩一区二区三区av | 成人精品在线 | 男女下面一进一出网站 | 日韩1区 | 亚洲一区有码 | 欧美日韩一区不卡 | 国产午夜视频 | 激情91| 亚洲精品欧美精品 | 国际精品鲁一鲁一区二区小说 |