【JavaScript OPP基礎】---新手必備

来源:http://www.cnblogs.com/hope666/archive/2017/05/14/6854443.html
-Advertisement-
Play Games

【JavaScriptOPP基礎】【成員屬性與成員方法】【原型與原型鏈】【原型屬性與原型方法】【for-in迴圈】【JS OOP 中的繼承】【JS模式實現繼承的三種方式】【閉包】 ...


今天和大家分享一下近期整理的有關JavaScriptOPP的基礎知識~~~我們一起來學習一下……

JavaScriptOPP基礎

一、面向對象編程OOP
1、語言的分類:
面向機器:彙編語言
面向過程:C語言
面向對象:C++,Java,PHP等
2、面向過程和麵向對象
①面向過程:專註於如何去解決一個問題的過程。
編程特點:用一個個函數去實現過程操作,沒有類和對象的概念;
②面向對象:專註於有哪一個對象實體去解決這個問題。
編程特點是:出現了一個個的類,由類去生成對象。

二、面向對象的三大特征
繼承,封裝,多態

三、類&對象的關係
1、類:一群有相同特征(屬性)和行為(方法)的集合
eg: 人類
屬性:"身高,體重,年齡"
方法:"吃飯,睡覺,敲代碼"

2、對象:從類中,new出的具有確定屬性值和方法的個體稱為對象。
eg:張三:屬性:身高:身高178,體重150 方法:說話---我叫張三

3、類和對象的關係:
類是抽象的,對象是具體的。
!類是對象的抽象化,對象是類的具體化!

通俗的來講:
類是一個抽象概念,表示具有相同屬性和行為的集合。
但是類僅僅表示表明這類群體具有相同的屬性,但是沒有具體的屬性值。
而對象是對類的屬性進行具體賦值後,而得到的一個具體的個體;

eg:人類有身高體重年齡,但不能具體說人類的身高體重具體是多少;而張三是人類的一個具體個體,身高體重等有具體值,則張三就是人類的一個對象。

4、使用類和對象的步驟:
①創建一個類(構造函數):
類名,必須要每個單詞首字母都大寫


function 類名(屬性一){
this.屬性 = 屬性一;
this.方法= function(){}
//this指向誰?即將調用當前構造函數的對象。
}


②通過類,實例化出一個新的對象;


var obj = new 類名(屬性一Value);
//原構造函數中this,指向新創建的obj對象
obj.方法();調用方法
obj.屬性();調用屬性
實例化對象的時候,會執行構造函數

5、兩個重要屬性:
constructor:返回當前對象的構造函數。(只有對象才有,返回的是構造函數-類)
>>>zhangsan.constructor == Person
>>>對象的constructor,位於_proto_原型對象上(後續講解)

instanceof:判斷對象是否是某個類的實例
>>>zhangsan instanceof Person true
>>>zhangsan instanceof Object true
>>>Person instanceof Object true(函數也是對象)

6、廣義對象與狹義對象:
廣義對象:除了用字面量聲明的基本數據類型之外,外物皆對象,換句話說,能夠添加屬性和方法的變數,就是對象;
var s = "1" ; 不是對象
var s = new String("1") ; 就是對象
狹義對象:只有屬性,方法,除此之外沒有任何東西。
var obj = {}; var obj = new Object();

 

成員屬性與成員方法
一、成員屬性與成員方法
1、在構造函數中通過this.屬性聲明;或者實例化出對象後,通過"對象.屬性"追加的。
都屬於成員屬性,或成員方法;也叫實例屬性與實例方法。

成員屬性/方法,是屬於實例化出的這個對象。
通過"對象.屬性"調用

二、靜態屬性與靜態方法
2、通過"類名.屬性名","類名.方法名"聲明的變數,稱為靜態屬性,靜態方法;也叫類屬性、類方法。

類屬性/類方法,是屬於類的(屬於構造函數的)
通過"類名.屬性名"調用

3、成員屬性,是屬於實例化出的對象的,會出現在新對象的屬性上
靜態屬性,是屬於類(構造函數)自己的,不會出現在新對象的屬性上

4、JS對象屬性的刪除:
①對象無需手動刪除,JS
②刪除對象的屬性:delete 對象名.屬性名

5、對象是引用數據類型
也就是說,當new出一個對象時,這個obj變數存儲的實際上是對象的地址,在對象賦值時,賦的也是地址。
function Person(){}
var xiaoxi = new Person();//xiaoxi對象實際上存的是地址
var ashu = xiaoxi;//賦值時,實際是將xiaoxi存的地址給了ashu
ashu.name = "阿樹";//阿樹通過地址,修改了地址
console.log(xiaoxi.name);//xiaoxi再通過地址打開對象,實際已經變了

引用數據類型,賦值時傳遞的是引用(地址)---快捷方式
基本數據類型,賦值時傳遞的是數據(值)

三、私有屬性和私有方法
6、在構造函數中,通過var聲明的屬性,成為私有屬性:
function Person(){var num=1;}

私有屬性的作用域,僅在當前函數有效。對外不公開,即通過對象/類都無法調用到。

原型與原型鏈

【__proto__與prototype】
1、prototype(函數的原型):函數才有prototype。
prototype是一個對象,指向了當前構造函數的引用地址。
2、__proto__(對象的原型對象):所有對象都有__proto__屬性。當用構造函數實例化(new)一個對象時,
會將新對象的__proto__屬性,指向構造函數的prototype。

eg:zhangsan.__proto__==Person.prototype √

所有對象最終都會指向Object()的prototype。

【原型鏈】
1、通過構造函數,new出的對象,新對象的__proto__指向構造函數的prototype。
2、所有函數的__proto__指向Function()的prototype。
3、非構造函數new出的對象({} new Object() 對象的prototype)的__proto__指向Object的prototype。
4、Object的__proto__指向Null。

原型屬性與原型方法

【類中屬性與方法的聲明方式】
1、成員屬性、成員方法:
this.name = ""; this.func = function(){}
>>>屬於實例化出的對象的。通過"對象.屬性"調用。

2、靜態屬性、靜態方法:
Person.name = ""; Person.func = function(){}
>>>屬於類(構造函數)的。通過"類名.屬性"調用。

3、私有屬性、私有方法:
在構造函數中,使用var num = 1;聲明
>>>只在構造函數內部能用,在外部無法通過任何方式訪問。

4、原型屬性、原型方法:
Person.prototype.name = "";
Person.prototype.func = function(){};
>>>寫在了構造函數的prototype上,當使用構造函數實例化對象時,該屬性方法會進入新對象的__proto__上。

也就是說,1/4使用對象可訪問,2使用類名可訪問,3只能在函數的{}內使用。

5、習慣上,我們會將屬性寫為成員屬性,而方法寫為原型方法;

eg:

1 function Person(){
2 this.name = "zhangsan";
3 }
4 Person.prototype.say = function(){}

 

原因:
①實例化出對象後,所有屬性直接在對象上,所有方法都在__proto__上,非常直觀清晰。
②方法寫到prototype上,要更加節省記憶體。
③使用for in 迴圈時,會將對象以及對象原型鏈上的所有屬性和方法列印出來,而方法往往是不需要展示的。
將方法寫到__proto__上,可以使用hasOwnProperty將原型上的方法更好的過濾。
④官方都這麼寫。

6、當訪問對象的屬性/方法時,會優先使用對象自有的屬性和方法。
如果沒有找到,便使用__proto__屬性在原型上查找,如果找到即可使用。
但是,當對象自身,以及__proto__上有同名方法,執行對象自身的。

7、可以通過prototype擴展內置函數的相關方法。

代碼演示:

 1 function Person(){
 2 this.name1 = "name1"; //成員屬性
 3 this.age = "age1";
 4 this.sex = "男";
 5 this.say = function(){
 6 alert("我是大帥哥!");
 7 }
 8 var name2 = "name2";//私有屬性
 9 }
10 Person.name3 = "name3";//靜態屬性
11 Person.prototype.name4 = "name4";//原型屬性
12 
13 
14 Person.prototype.say = function(){
15 alert("我叫"+this.name1);
16 }
17 
18 var zhangsan = new Person();
19 //    zhangsan.say = function(){
20 //    alert("我是大帥哥!");
21 //    }
22 zhangsan.say();
23 zhangsan.toString();
24 
25 console.log(zhangsan);
26 
27 //    console.log(zhangsan.name1);
28 //    console.log(zhangsan.name2);
29 //    console.log(zhangsan.name3);
30 //    console.log(zhangsan.name4);
31 //    
32 //    console.log(s);

 

可以通過prototype擴展內置函數的相關方法

代碼演示:

 1 Number.prototype.add = function(a){
 2 return this+a
 3 }
 4 
 5 var num = new Number(10);
 6 console.log(num);
 7 alert(num.add(3));
 8 
 9 /*
10 * 為Array類添加一個find(val)方法,當一個Array對象調用該方法的時候,如果能找到val值,則返回其下標,否則返回-1。
11 */
12 Array.prototype.find = function(val){
13 for (var i = 0; i<this.length;i++) {
14 if(this[i]==val){
15 return i;
16 }
17 }
18 return -1;
19 }
20 var arr = new Array(1,2,3,4,5);
21 alert(arr.find(1));

 



位String類添加一個字元串反轉方法

 1 String.prototype.fanzhuan = function(){
 2 var arr = this.split("");
 3 arr.reverse();
 4 return arr.join("")
 5 }
 6 
 7 
 8 console.log(str.fanzhuan());
 9 
10  
11 
12 for-in迴圈
13 
14 
15for-in迴圈】
16 for-in迴圈,主要用於遍歷對象。
17 for()中格式:for(keys in obj){}
18 
19 keys表示obj對象的每一個鍵值對的鍵,所以{}中,使用obj[keys]讀取每個值;
20 但是,使用for-in迴圈,不但能遍歷對象本身的屬性和方法。還能夠遍歷對象原型鏈上的所有屬性和方法。
21 
22 可以使用hasOwnProperty判斷一個屬性,是否是對象自身的屬性。
23 obj.hasOwnProperty(keys)==true 表示:keys是對象自身的一個屬性
24 
25 代碼演示:
26 // foreach
27 function Person(){
28 this.name1 = "name11111"; //成員屬性
29 this.age = "age11111";
30 this.func2 = function(){
31 console.log("thisFun")
32 }
33 }
34 Person.name3 = "name333333";
35 Person.prototype.name4 = "name44444";
36 Person.prototype.func1 = function(){
37 console.log("prototypeFun")
38 }
39 var zhangsan = new Person();
40 for(keys in zhangsan){
41 if(zhangsan.hasOwnProperty(keys)){ //過濾掉原型上的屬性,只列印對象自身屬性
42 console.log(zhangsan[keys])
43 }
44 }

 

JS OOP 中的繼承【JS模式實現繼承的三種方式】

【文檔註釋】第一行兩個星號
/**
* ……
*/
調用函數時,可以看到註釋內容

【JS OOP 中的繼承】
1、使用一個子類繼承另一個父類,子類可以自動擁有父類的屬性和方法。

>>>繼承的兩方,發生在兩個類之間。

2、JS模式實現繼承的三種方式:

1)擴展Object實現繼承

①定義父類:function Parent(){}
②定義子類:function Son(){}
③通過原型給Object對象添加一個擴展方法。

1 Object.prototype.customExtend = function(parObj){
2 for(var i in parObj){
3 //通過for-in迴圈,把父類的所有屬性方法,賦值給自己。
4 this[i] = ParObj[i];
5 }
6 }

 

④子類對象調用擴展方法
son.customExtend(Parent);

2)使用call和apply
首先,瞭解一下call和apply:通過函數名調用方法,強行將函數中的this指向某個對象;
call寫法:func.call(func的this指向的obj,參數1,參數2...);
apply寫法:func.apply(func的this指向的obj,[參數1,參數2...]);
call與apply的唯一區別:在於接收func函數的參數方式不同。call採用直接寫多個參數的方式,而apply採用是一個數組封裝所有參數。
①定義父類 funtion Parent(){}
②定義子類 function Son(){}
③在子類中通過call方法或者apply方法去調用父類。
function Son(){
Parent.call(this,....);
}
3)使用原型繼承
①定義父類function Parent(){}
②定義子類function Son(){}
③把在子類對象的原型對象聲明為父類的實例。
Son.prototype = new Parent();

 

閉包

【JS中的作用域】

1、全局變數:函數外聲明的變數
局部變數:函數內聲明的變數

在JS中,函數為唯一的局部作用域,而if、for等其他{}沒有自己的作用域
所以,函數外不能訪問局部變數。
其實,變數在函數執行完畢以後,占用的記憶體就被釋放。

2、如何訪問函數私有變數?
JS中,提供了一種"閉包"的概念:在函數內部,定義一個子函數,可以用子函數訪問父函數的私有變數。執行完操作以後,將子函數通過return返回。

 1 function func2(){
 2 var num = 1;
 3 function func3(){
 4 var sum = num+10;
 5 alert(sum);
 6 }
 7 return func3;
 8 }
 9 var f = func2();
10 f();

 

3、閉包的作用:
① 訪問函數的私有變數;
② 讓函數的變數始終存在於記憶體中,而不被釋放。


代碼演示:

 1 function func1(){
 2 var n = 1;
 3 }
 4 if(true){
 5 var m = 3;
 6 }
 7 //alert(m); // 3
 8 func1();
 9 //alert(n);// 報錯。函數外不能訪問局部變數。其實,n變數在func1函數執行完畢以後,占用的記憶體就被釋放。
10 
11 
12 /*閉包*/
13 function func2(){
14 var num = 1;
15 function func3(){
16 var sum = num+10;
17 alert(sum);
18 }
19 return func3;
20 }
21 var f = func2();
22 f();
23 
24 // 迴圈轉一次,創建一個lis[i].onclick函數。但是,當點擊li執行函數的時候,i已經變為6,所以無論點擊哪一個,i都是6
25 // 迴圈創建lis[i].onclick的時候, 迴圈一次,li[i]裡面的i都被賦為不同值;創建了 li[1] li[2] li[3]...
26 // 但是,創建過程中,並沒有執行onlick後面的函數,所以函數裡面的i並沒有賦值,還是字母i。
27 // 最終,我們點擊li[1] li[2]...時,onclick函數裡面的i才會賦值。(但此時,全局變數的i ,已經成為6 了)
28 var lis = document.getElementsByTagName("li");
29 for (var i=0;i<lis.length;i++) {
30 lis[i].onclick = function(){
31 //alert("您/點擊了第"+i+"個li!");
32 //console.log(lis[i]);
33 //console.log(this);
34 }
35 }
36 
37 // 迴圈轉一次,創建一個自執行函數。
38 // 而自執行函數擁有自己的作用域,所以用函數局部作用域j保存當前的全局變數i值。這樣,創建第一個自執行函數,它的j=1;創建第二個,它的j=2...不同函數的j互不幹擾。
39 // 這樣,迴圈轉完以後,相當於創建了6個自執行函數,每個函數中都有一個不同的j變數
40 var lis = document.getElementsByTagName("li");
41 for (var i=0;i<lis.length;i++) {
42 !function(){
43 var j = i;
44 lis[j].onclick = function(){
45 alert("您/點擊了第"+j+"個li!");
46 //console.log(lis[i]);
47 //console.log(this);
48 }
49 }();
50 }
51 
52 var lis = document.getElementsByTagName("li");
53 for (var i=0;i<lis.length;i++) {
54 !function(j){
55 lis[j].onclick = function(){
56 alert("您/點擊了第"+j+"個li!");
57 //console.log(lis[i]);
58 //console.log(this);
59 }
60 }(i);
61 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目描述 “低價購買”這條建議是在奶牛股票市場取得成功的一半規則。要想被認為是偉大的投資者,你必須遵循以下的問題建議:“低價購買;再低價購買”。每次你購買一支股票,你必須用低於你上次購買它的價格購買它。買的次數越多越好!你的目標是在遵循以上建議的前提下,求你最多能購買股票的次數。你將被給出一段時間內 ...
  • 1、www.bejson.com線上json格式校驗工具 2、關聯兩種方式:正則表達式和json path 名稱+$. 3、charles 抓包工具,獲取介面請求方式、response、cookies和報文等信息,方便進行測試 連接手機端:proxy setting 獲取電腦的ip 修改手機 操作手 ...
  • 類與對象是不同的,類是對象的藍本,你創建出來的是對象,而它的結構由類預先定義。對象是一些操作(方法)和信息(屬性)的集合,並占據記憶體中的一塊存儲空間,你可以通過函數調用的方式讓它對它的屬性執行默寫操作。 摘自 [美】 Alasdair Allan <Learning iOS Programming> ...
  • 本篇博客是《JWebFileTrans(JDownload):一款可以從網路上下載文件的小程式》系列博客的第三篇,本篇博客的內容主要是在前兩篇的基礎上增加多線程的功能。簡言之,本篇博客截止目前所達到的功能是:基於HTTP協議的多線程斷點遠程下載小程式 ...
  • 1.所有的標記都必須要有一個相應的結束標記 以前在HTML中,你可以打開許多標簽,例如<p>和<li>而不一定寫對應的</p>和</li>來關閉它們。但在XHTML中這是不合法的。XHTML要求有嚴謹的結構,所有標簽必須關閉。如果是單獨不成對的標簽,在標簽最後加一個"/"來關閉它。 2.所有標簽的元 ...
  • 示例html代碼: 獲得id為test的DOM對象,下麵就不一一獲取了。 test.innerHTML 描述:也就是從對象的起始位置到終止位置的全部內容,包括Html標簽。 上例中的test.innerHTML的值也就是“<span style="color:red">test1</span> te ...
  • 一、安裝node.js 方式很多npm,git等,新手建議從官網上直接去下載node的安裝包。一鍵安裝. 二、創建一個web伺服器。 三、讀取文件的方式(同步,非同步) 1.同步 2.非同步 三、事件迴圈 四、數據緩衝區 1.向緩存區寫入數據 2.讀取緩衝區的內容 3.Buffer 轉為JSON對象 4 ...
  • 3.下拉列表:<select name="" id=""> <option value=""></option> </select> 屬性:name="" 指定獲取輸入的名字。 value="" 不知道有什麼用。但我知道它有用。 在option標簽中預設選中屬性為 selected 在input標簽 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...