構造函數和原型
構造函數和原型
在典型的OOP 的語言中(如Java),都存在類的概念,類就是對象的模板,對象就是類的實例,但在ES6之前,JS 中并沒用引入類的概念。ES6,全稱ECMAScript6.0 ,2015.06 發版。但是目前瀏覽器的JavaScript 是ES5 版本,大多數高版本的瀏覽器也支持ES6,不過只實現了ES6 的部分特性和功能。在ES6之前,對象不是基于類創建的,而是用一種稱為構建函數的特殊函數來定義對象和它們的特征。
創建對象可以通過以下三種方式:
- 對象字面量
var obj = {// 屬性名 :屬性值// 鍵值對// 成員name : '張三豐',age : 22,sex : '男',lanqiu : function () {console.log('打籃球');}};// obj.keyvar wahahaobj = {}// console.log( obj );// console.log( obj.lanqiu );// console.log( obj.age );// obj.lanqiu();// console.log( obj.name );// console.log( obj['name'] );// 遍歷對象for ( var key in obj ) {console.log( obj[key] );// console.log( obj.key );}
- new Object()【構造函數】
構造函數也是函數,只不過用法不同,需要和new一起使用才有意義,就可以new出來一個對象// 構造函數創建對象var o = new Object();// console.log( o instanceof Object );// console.log( n instanceof Array );// console.log( o );// 添加屬性// 設置:對象.屬性名 = 值;o.uname = '李尋歡';o.age = 22;o.fei = function () {console.log('’飛飛飛');};// console.log( o.uname );// o.fei();
- 自定義構造函數
function Person (uname, age) {this.uname = uname;this.age = age;this.chang = function () {console.log('change');}
}// var obj = new Person();// console.log(obj);var obj = new Person('假冰冰', 22);console.log( obj );var obj1 = new Person('劉德華', 17);console.log(obj1);
課件練習:自定義一個構造函數,可以new出一個對象,屬性:姓名,年齡,性別,武器方法:打人,逃跑function Hero (uname, age, sex, weapon) {this.uname = uname;this.age = age;this.sex = sex;this.weapon = weapon;// 方法this.gongji = function () {console.log('打打打');}this.pao = function () {console.log('跑跑跑,趕緊跑eqdfabcdf連氣泡');}}// 實例化var hz = new Hero('皇子', 16, '男', '矛');// console.log( hz );console.log( hz.uname );hz.pao();
工廠模式
構造函數和原型
構造函數是一種特殊的函數,主要用來初始化對象,即為對象成員變量賦初始值,它總與new一起使用。我們可以把對象中一些公共的屬性和方法抽取出來,然后封裝到這個函數里面。function Fn () {}
在JS 中,使用構造函數時要注意以下兩點:
1.構造函數用于創建某一類對象,其首字母要大寫
2.構造函數要和new 一起使用才有意義
練習判斷構造函數還是普通函數在使用的時候查看是否與new結合使用
new在執行時會做四件事情
- 在內存中創建一個新的空對象。
- 讓this指向這個新的對象。
- 執行構造函數里面的代碼,給這個新對象添加屬性和方法。
- 返回這個新對象(所以構造函數里面不需要return)。
靜態成員和實例成員
JavaScript 的構造函數中可以添加一些成員,可以在構造函數本身上添加,也可以在構造函數內部的this 上添加。通過這兩種方式添加的成員,就分別稱為靜態成員和實例成員。
- 靜態成員:在構造函數本上添加的成員稱為靜態成員,只能由構造函數本身來訪問
- 實例成員:在構造函數內部創建的對象成員稱為實例成員,只能由實例化的對象來訪問
function Person (uname, age) {this.uname = uname;this.age = age;this.say = function () {console.log(123);}}var obj = new Person('張三豐',22); console.log(obj.uname);// console.log( Person.uname );Person.leibie = '人';console.log(Person.leibie);console.log(obj.leibie);
? ES6:字面量,構造函數,自定義構造函數
? new執行過程:1.創建空對象,2.this指向這個對象,3.指向函數里面的代碼,4.返回這個對象
? 成員:靜態成員【Star.sex = ‘男’】,實例成員【function Star () {成員}】
構造函數小問題:
當實例化對象的時候,屬性好理解,屬性名屬性值,那么方法是函數,函數是復雜數據類型那么保存的時候是保存地址,又指向函數,而每創建一個對象,都會有一個函數,每個函數都得開辟一個內存空間,此時浪費內存了,那么如何節省內存呢,我們需要用到原型方法放到構造函數里面,如果多次實例化,會浪費內存
function Star (uname, age) {this.uname = uname;this.age = age;this.sing = function () {console.log(this.name + '在唱歌');}
}var ldh = new Star('周星馳', 22);
var ldh = new Star('劉德華', 22);
構造函數原型prototype
什么是原型對象:就是一個屬性,是構造函數的屬性,這個屬性是一個對象,我們也稱呼,prototype 為原型對象。
每一個構造函數都有一個屬性,prototype
作用:是為了共享方法,從而達到節省內存
注意:每一個構造函數都有prototype屬性
例如:大家來學校上學,有的開車,有的汽車,有的開飛機,等等,此時浪費,那么準備一個大巴車,方便有節省
構造函數通過原型分配的函數是所有對象所共享的。
JavaScript 規定,每一個構造函數都有一個prototype 屬性,指向另一個對象。注意這個prototype 就是一個對象,這個對象的所有屬性和方法,都會被構造函數所擁有。我們可以把那些不變的方法,直接定義在prototype 對
象上,這樣所有對象的實例就可以共享這些方法。
function Star (uname, age) {this.uname = uname;this.age = age;// this.sing = function () {// console.log(this.name + '在唱歌');// }}Star.prototype.sing = function () {console.log(this.uname + '在唱歌');}var zxc = new Star('周星馳', 22);var ldh = new Star('劉德華', 22);// console.log( Star.prototype );ldh.sing();zxc.sing();
總結:所有的公共屬性寫到構造函數里面,所有的公共方法寫到原型對象里面
疑問:為何創建一個對象,都可以自動的跑到原型對象上找方法
因為每一個對象都有一個屬性,對象原型,執行原型對象
對象原型:proto
主要作用:指向prototype
構造函數和原型對象都會有一個屬性____proto____ 指向構造函數的prototype 原型對象,之所以我們對象可以使用構造函數prototype 原型對象的屬性和方法,就是因為對象有__proto__ 原型的存在。
注意:____proto____是一個非標準屬性,不可以拿來賦值或者設置【只讀屬性】
-
1.____proto____對象原型和原型對象prototype 是等價的2.____proto____對象原型的意義就在于為對象的查找機制提供一個方向,或者說一條路線,但是它是一個非標準屬性,因此實際開發中,不可以使用這個屬性,它只是內部指向原型對象prototype
總結:每一個對象都有一個原型,作用是指向原型對象prototype
統一稱呼:____proto____原型,prototype成為原型對象
每一個構造函數都有一個:prototype【原型對象】(作用:存方法)每一個對象都有一個:__proto__對象原型,(作用:指向prototype)
constructor 構造函數
記錄是哪個構造函數創建出來的
指回構造函數本身
原型(proto)和構造函數(prototype)原型對象里面都有一個屬性constructor屬性,constructor 我們稱為構造函數,因為它指回構造函數本身。constructor 主要用于記錄該對象引用于哪個構造函數,它可以讓原型對象重新指向原來的構造函數。一般情況下,對象的方法都在構造函數的原型對象中設置。如果有多個對象的方法,我們可以給原型對象采取對象形式賦值,但是這樣就會覆蓋構造函數原型對象原來的內容,這樣修改后的原型對象constructor 就不再指向當前構造函數了。此時,我們可以在修改后的原型對象中,添加一個constructor 指向原來的構造函數。
總結:constructor 主要作用可以指回原來的構造函數
構造函數、實例、原型對象三者之間的關系
1、每個構造函數都有一個屬性:prototype(原型對象),作用:存方法節省內存
2、每個對象都有一個屬性:proto(對象原型),作用:指向prototype
3、每個原型對象都有一個屬性:constructor,作用:指回構造函數本身
思考:如果傳入一個對象給原型對象添加方法呢
Star.prototype = {sing : function () {},dance: function () {}
};此時會覆蓋原先prototype中的內容,傳入一個新的對象,那么此時就不知道構造函數是哪個了
所以我們要指回構造函數:constructor:構造函數
課程回顧:
? 1、創建對象:字面量,構造函數,自定義構造函數
? 2、new執行過程:創建新對象,this指向這個對象,執行代碼,返回這個對象
? 3、靜態成員實例成員:
? 構造函數身上的成員,稱為靜態成員,只能由構造函數去訪問
? 構造函數內部的成員,稱為實例成員,只能由實例對象去訪問
? 4、原型對象:構造函數的一個屬性,prototype(原型對象),作用:存方法省內存
? 5、對象原型:對象的一個屬性(proto),作用:指向prototype
? 6、構造函數:constructor,作用:指回構造函數本身