JavaScript學習(四)-面向對象編程

創建對象
JavaScript對每個創建的對象都會設置一個原型,指向它的原型對象
如果用obj.xxx訪問一個對象屬性時,JavaScript引擎先在當前對象上查找該屬性,如果沒有找到,就到其原型對象上找,如果還沒有找到,就一直上溯到Object.prototype對象,最後還沒找到,就返回undefined
Array.prototype定義了indexOf(),shift()等方法,因此可以在Array對象上直接調用這些方法
創建一個函數,該函數也是一個對象,Function.prototype定義了apply()等方法,所有函數都可以調用方法
var arr=[1,2,3];
//原型鏈:arr----->Array.prototype------->Object.prototype------>null
function fun(){
	return 0;
}
//原型鏈:function------>Function.prototype------>Object.prototype----->null

構造函數

function Person(name){
	this.name=name;
	this.hello=function(){
		alter('Hello,'+this.name+'!');
	}
}
//雖然看起來是給普通函數,但是用new關鍵字調用這個函數,返回一個對象
var bob=new Person('bob');
bob.name;//'bob'
bob.hello();//Hello,bob!
//bob的原型鏈:bob---->Person.prototype--->Object.prototype--->null
//new Person()創建的對象從原型上獲得constructor屬性,指向函數Person本身

學習廖雪峯知識截圖

xiaoming.constructor===Student.prototype.constructor;//true
Student.prototype.constructor===Student;//true
Object.getPrototypeOf(xiaoming)===Student.prototype;//true
xiaoming instanceof Student;//true
通過new創建不同對象,雖然函數名稱和代碼相同,但是實際上是不同的
這些對象實際上共享同一個函數可以節省很多內存
只需把函數移動到對象共有的原型上就可以了,即Person.prototype
//修改如下
function Person(name){
	this.name=name;
}
Person.prototype.hello=function(){
	alter('Hello,'+this.name+'!');
}
約定:構造函數首字母應當大寫,普通函數首字母應該小寫
編寫一個createStudent()函數,內部封裝所有的new操作
function Student(props){
	this.name=props.name||"匿名"//設置默認值
	thid.grade=props.grade||1;
}
Student.prototype.hello=function(){
	alert('hello,'+this.name+'!');

};
function createStudent(props){//不需要new來調用,參數非常靈活,可以不傳也可以這麼傳
	return new Student(props||{});
}
var bob=createStudent({name:'bob'});//如果創建的對象有很多屬性,只需要傳遞需要的某些屬性,剩下的屬性用默認值,如何從JSON拿到一個對象,可以直接創建出bob
bob.grade;//1

原型繼承

function Student(props){
	this.name=props.name||'Unnamed';
}
Student.prototype.hello=function(){
	alert('hello,'+this.name+'!');
}

Student原型鏈
必須藉助一箇中間對象來實現正確的原型鏈,這個中間對象的原型指向Student.prototype

//PrimaryStudent構造函數
function PrimaryStudent(props){
	Student.call(this,props);
	this.grade=props.grade||1;
}
//空函數f
function F(){}
//把F的原函數指向Student.prototype
F.prototype=Student.prototype;
//把PrimaryStudent的原型指向一個新的F對象,F對象的原型正好指向Student.prototype
PrimaryStudent.prototype=new F();
//把PrimaryStudent的原型的構造函數修復爲PrimaryStudent
PrimaryStudent.prototype.constructor=PrimaryStudent;
//繼續在PrimaryStudent原型(new F()對象)上定義方法
PrimaryStudent.prototype.getGrade=function(){return this.grade;};
//創建xiaoming
var xiaoming=new PrimaryStudent({
	name:'小明',
	grade:2

});
xiaoming.name;//小明
xiaoming.grade;//2
//驗證原型
xiaoming._proto_===PrimaryStudent.prototype;//true
xiaoming._proto_._proto_===Student.prototype;//true
//驗證繼承
xiaoming instanceof PrimaryStudent;//true
xiaoming instanceof Student;//true

新的原型圖也可以用inherits()函數封裝起來,隱藏F的定義

function inherits(Child,Parent){
	var F=function(){};
	F.prototype=Parent.prototype;
	Child.prototype=new F();
	Child.prototype.constructor=Child;
}
function Student(props){
this.name=props.name||'bob';
}
Student.prototype.hello=function(){
alert('hello,'+this.name+'!');
}
function PrimaryStudent(props){
Student.call(this.props);
this.grade=props.grade||1;
}
inherts(PrimaryStudent,Student);
PrimaryStudent.prototype.getGrade=function(){
return this.garde;
}

class 繼承

class關鍵字在ES6正式引用,
class Student{
	constructor(name){
	this,name=name;
	}
	hello(){
		alert('hello'+this.name+'!');
	}
}
class PrimaryStudent extends Student{
	constructor(name,grade){
		super(name);
		this.grade=grade;
	}
	myGrade(){
		alert('I am at grade'+this.grade);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章