一、面向對象
- 面向過程:凡事親力親為,每件事的具體過程都要知道,注重過程
- 面向對象:根據需求尋找對象,所有的事都用對象來做,注重結果
- 面向對象特性:封裝、繼承、多態(抽象性)
- js是一門基於對象的語言:js不是面向對象的語言,但是可以模擬面向對象的思想
- 對象是定義:有特征和行為,具體特指某一事物
二、創建對象的方法
1. 調用系統的構造函數創建對象
var obj=new Object();//關鍵詞Object,大寫首字母 obj.name="小明"; obj.age=20; obj.sex="男"; obj.play=function(){ console.log("我在玩游戲"); }; obj.showName=function(){ console.log("我叫"+this.name) } console.log(obj.name);//小明 console.log(obj.age);//20 console.log(obj.sex);//男 obj.play();//我在玩游戲 obj.showName();//我叫小明
- 這種方法通過new關鍵字生成一個對象,然后根據JavaScript是動態語言的特性來添加屬性和方法,構造一個對象。
- 在當前的對象的方法中,可以使用this代替當前對象
- 這種方法的問題在於:如果我們需要多次創建對象,那么就需要重復代碼多次,不利於代碼的復用。
2.工廠模式:一次性創建多個對象——工廠模式創建對象:利用函數封裝起來,后面調用
- 原始版本
function creatObj(){ var obj= new Object(); obj.name="關羽"; obj.age=30; obj.showName=function(){ console.log("我叫"+this.name); }; obj.showAge=function(){ console.log("我今年"+this.age); }; return obj; } var obj1=creatObj(); var obj2=creatObj(); obj1.showName();//我叫關羽 obj1.showAge();//我今年30 obj2.showName();//我叫關羽 obj2.showAge();//我今年30
這種方法雖然也實現了創建對象,但是同樣地,如果需要多次創建對象,而且屬性內容不一樣的話,也是需要重復代碼多遍。需要重新考慮代碼重用率,接下來修改代碼,使其可以提高代碼重復率,而且可以改變工廠方法,傳入參數賦值。
-
改進版本
function creatObj(name,age){ var obj= new Object(); obj.name=name; obj.age=age; obj.showName=function(){ console.log("我叫"+this.name); }; obj.showAge=function(){ console.log("我今年"+this.age); }; return obj; } var obj1= new creatObj("劉備",32); var obj2= new creatObj("關羽",30); obj1.showName();//我叫劉備 obj1.showAge();//我今年32 obj2.showName();//我叫關羽 obj2.showAge();//我今年30
這種方法雖然可以提高代碼的重用率,但和面向對象中類的概念相比,有一個很大的缺陷。
面向對象強調對象的屬性私有,但對象的方法是共享。而上面的工廠方法在創建對象時,要為每個對象創建各自私有的方法。
同時,由於為每個對象都創建邏輯相同的方法,所以很浪費內存。
-
最終版本
function creatObj(name,age){ var obj= new Object(); obj.name=name; obj.age=age; obj.showName=showName; obj.showAge=showAge; return obj; } showName=function(){ console.log("我叫"+this.name); }; showAge=function(){ console.log("我今年"+this.age); }; var obj1=new creatObj("劉備",32); var obj2=new creatObj("關羽",30); obj1.showName();//我叫劉備 obj1.showAge();//我今年32 obj2.showName();//我叫關羽 obj2.showAge();//我今年30
上面通過定義幾個函數對象,解決了不同對象持有函數對象的私有問題。現在所有對象的方法都持有上面兩個函數的引用。
但是這么一來,對象的函數和對象又相互獨立,這和面向對象中特定方法屬於特定類的思想不符合。
3.自定義構造函數創建對象(結合第一種和需求,通過工廠模式創建)
function Person(name,age){ this.name=name; this.age=age; this.showName=function(){ console.log("我叫"+this.name); }; this.showAge=function(){ console.log("我今年"+this.age); }; }; var obj1=new Person("劉備","32"); var obj2=new Person("關羽","30"); obj1.showName();//我叫劉備 obj1.showAge();//我今年32 obj2.showName();//我叫關羽 obj2.showAge();//我今年30
- 構造函數的方法和工廠方法一樣,會為每個對象創建獨享的函數對象。當然也可以將這些函數對象定義在構造函數外面,這樣有了對象和方法相互獨立的問題。
- 使用構造函數存在的最大問題就是每個實例都會將所有的屬性創建一次。這個對於數值屬性來說可以接受,但是如果函數方法每個實例都要創建一遍,則不合理。
- 自定義構造函數: 沒有var、沒有返回值、用this代替當前對象
- 要創建Person()的新實例,必須使用new操作符。
- 構造函數和函數的區別:構造函數的名字首字母一般大寫
- 自定義構造函數創建對象做了四件事:
- 在內存中開辟(申請)空間,存儲新的對象
- 把this設置新的對象
- 設置對象的屬性和方法的值
- 把this這個對象返回
4.字面量創建對象
var obj={ name:"劉備", age:32, height:"180cm" } console.log(obj.name);//劉備 console.log(obj.age);//32 console.log(obj.height);//180cm console.log(obj instanceof Object);//true
- 字面量創建的對象的缺陷:一次性的對象
- 注意屬性與屬性之間用逗號,不是分號
三、一些結論
1.如何獲取該變量(對象)是不是屬於什么類型?
- 語法: 變量 instanceof 類型的名字 -------布爾類型,輸出是true或者false
- 類型的名字首字母大寫
var obj={ name:"張飛", age:32, }; console.log(obj instanceof Object);//true
2.對象是一組有序屬性的集合,屬性的值可以是任意的類型
3.點語法:沒有什么就點什么,可以設置和獲取和獲取對象屬性
var obj={ name:"劉備", age:32, }; obj.height="180cm";//添加height屬性 console.log(obj.name);//劉備 console.log(obj.age);//32 console.log(obj.height);//180cm
4.設置和獲取屬性的另外一種方法是通過[ " " ],必須有雙引號
var obj={ name:"關羽", age:"30", }; obj["height"]="190cm";//添加height屬性 console.log(obj["name"]);//關羽 console.log(obj["age"]);//30 console.log(obj["height"]);//190cm
5.Json
var obj={ "name":"劉備", "age":"32", "height":"180cm" }
- json格式的數據,一般都是成對的,鍵值對的形式
- json也是一個對象,數據無論是鍵還是值都是用雙引號括起來的
- json不能通過for循環遍歷,因為是無序的,但是可以通過for……in 循環遍歷
var json={ "name":"某某", "age":"18", "height":"180cm" } //通過點語法和[]訪問 console.log(json.name);//某某 console.log(json["age"]);//18 //定義一個變量 var key="age"; console.log(json[key]);//18 //推出使用for...in循環遍歷 for(var key in json){ console.log(key);//name age height console.log(json[key]);//某某 18 180cm console.log(json.key);//undefined 因為點語法會添加一個key屬性,而沒有值 }
6.數據類型
- 原始數據類型:Number、String、Boolean、undefined、null、Object
- 基本類型(簡單類型、值類型):Number、String、Boolean
- 復雜類型(引用類型):Object
- 空類型:undefined、null
- 值類型在棧中存儲,引用類型在堆和棧上存儲-----對象在堆存儲,對象的地址在棧存儲
- 值類型傳遞的是值,引用類型傳遞的是地址(引用)
//例1: var obj={ name:"李白" }; function f2(obj2){ obj2.name="韓信"; } console.log(obj.name);//李白 f2(obj); console.log(obj.name);//韓信
//例2:
var num=50; function f1(num){ num=60; console.log(num);//60 } f1(num); console.log(num);//50
//例3: var num1=55; var num2=66; function f1(num,num1){ num=100; num1=100; num2=100; console.log(num);//100 console.log(num1);//100 console.log(num2);//100 } f1(num1,num2); console.log(num1);//55 console.log(num2);//100 console.log(num);//報錯
//例4: function Person(name,age,salary){ this.name=name; this.age=age; this.salary=salary; } function f1(person){ person.name="張三"; person=new Person("李四",18,10); } var p=new Person("趙六",18,1000); console.log(p.name);//趙六 f1(p); console.log(p.name);//張三