天天看點

Python學習筆記:5.2.5 javascript面向對象

本文是學習陸老師的《python全棧工程師 - web開發前端基礎》課程的筆記,歡迎學習交流。同時感謝陸老師的精彩傳授!

一、課程目标

  • 工廠模式
  • 構造函數模式
  • 原型模式

二、詳情解讀

2.0.引用類型練習

練習1:

請建立一個函數,可以根據輸入不同的姓名,年齡、性别,建立不同的使用者執行個體

function createUser(name, age, sex){
	var  o = new Object()
	o.name = name
	o.age  = age
	o.sex  = sex
	o.toString = function(){
		return "我的名字" + o.name + "我的年齡:"+o.age + "性别:" + o.sex
	}
	return o
}
wangsan = createUser("wangsan", 18, "girl")
console.log(wangsan)
           

運作結果:

Python學習筆記:5.2.5 javascript面向對象

練習2:

寫一個copy對象的函數,實作兩個對象之間值相等,但不是同一個對象,比如 obj2拷貝obj1中的每一項,但是obj1的修改不影響obj2(淺拷貝與深拷貝)

function copyObject(object){
   var o = new Object()
   for (i in object){
   	// 深拷貝
	  /* if (typeof(object[i]) == "object"){
		   o[i] = copyObject(object[i])
	   } else {
		   o[i] = object[i]
	   } */
	   // 淺拷貝
		o[i] = object[i]
   }
   return o
}
var obj = new Object()
obj.name = {first:"luxp", last:"pp"}
obj.age = 18
           

深拷貝運作結果:(當obj的name.first屬性改變時,obj_2的name.first屬性沒有變化)

Python學習筆記:5.2.5 javascript面向對象

淺拷貝運作結果:(obj的屬性改變,obj_2的也發生改變)

Python學習筆記:5.2.5 javascript面向對象

練習3:

系統有這麼一些商品:(洗衣機,3000元), (筆記本電腦,12000元),(音箱,1000),請使用合适的方式表示這一組商品

goods = []
goods[0] = ["洗衣機",3000],
goods[1] = {"筆記本電腦":12000}
goods[2] = {"音箱": 1000}
           

練習4:

實作一個FIFO隊列對象,隻有兩個方法put(向隊列寫入資料)與 get(從隊列中讀取資料)

var queue = new Object()
   queue.data = []
   queue.put = function(val){
	  queue.data.push(val)
   }
   queue.get = function(){
	  return queue.data.shift()
   }
           

練習5:

[{“name”:“luxp”},{“name”:“wangsan”}, {“name”:“ls”}, {“name”:“ns”} ]

使用sort按照name的值排序

array = [{"name":"luxp"},{"name":"wangsan"}, {"name":"ls"}, {"name":"ns"} ]
function compare(val1,val2){
   if (val1.name > val2.name){
	   return true
   } else {
	   return false
   }
}
sorted_array = array.sort(compare)
           

練習6:

使用filter 挑出 5的倍數

array = [1,3,5,8,10,15] 
new_array = array.filter(function(val){
   if (val%5==0){
	   return true
   }
   
})
           

練習7:

有這麼一份商品價格資料

[“商品名稱”,商品價格,銷售額]

[[“good1”,1000,5000],[“good2”,1200,3600],[“good3”,1500,6000],

[“good4”,1000,2000],[“good5”,1300,5200],[“good6”,1400,5600]]

統計一下,價格在1200以上(不包含1200)的商品銷售總額

array = [["good1",1000,5000],["good2",1200,3600],["good3",1500,6000],
["good4",1000,2000],["good5",1300,5200],["good6",1400,5600]]

function compare(pre,cur){
  console.log("cur",cur,cur[0])
  if (cur[1]>1200){
	  return pre+cur[2]
  } else {
	  return pre
  }
  
}
res = array.reduce(compare, 0)
           

運作結果:

Python學習筆記:5.2.5 javascript面向對象

** 練習8:

找出往後500年的閏年,并console中輸出出來

閏年計算方法:

普通年能被4整除且不能被100整除的為閏年

世紀年能被400整除的是閏年。(如2000年是閏年,1900年不是閏年)**

date = new Date()
 year = date.getFullYear()
 for (i=0;i<=500; i++,year++){
	if (year%4==0 && year%100!=0){
		console.log(year) 
	}
	if (year%100==0 && year%400==0){
		console.log(year)
	}
 }
           

運作結果:

Python學習筆記:5.2.5 javascript面向對象

練習九:

注冊使用者要求: 不能含有kefu, kf,admin等字元,并且以任意英文字母開頭,包含英文或者數字,

最短不能少于5個字元,最長不能超過15個字元,寫一個使用者輸入驗證函數

reg1 = new RegExp("^[a-z]\\w{4,14}$")
reg2 = new RegExp("(kf)|(kefu)|(admin)")
function validateUserName(user_name){
	if (!reg1.test(user_name)){
		return false
	}
	if (reg2.test(user_name)){
		return false
	}
	return true
}
           
2.1.工廠模式
// 通過函數來建立對象,稱為工廠模式:
function createObj(id, name, val) {
	var o = new Object()
	o.id = id
	o.name = name
	o.val = val
	return o
}
o1 = createObj(1, 'first', 10)
o2 = createObj(2, 'second', 20)
           
工廠模式的缺點:建立對象沒有特定類型

代碼示例:

function createUser(name, age, sex){
	var  o = new Object()
	o.name = name
	o.age  = age
	o.sex  = sex
	o.toString = function(){
		return "我的名字" + o.name + "我的年齡:"+o.age + "性别:" + o.sex
	}
	return o
}
wangsan = createUser("wangsan", 18, "girl")
           
2.2.構造函數模式
function Person(name, age, sex) {
	this.name = name
	this.age = age
	this.sex = sex
}

wangSan = new Person('wang san', 18, 'man')
cuihua = new Person('cuihua', 20, 'woman')
           

通過構造函數模式,可以建立自己的類型

構造函數是通過new關鍵字建立函數執行個體對象

代碼示例:

function Person(name, age, sex) {
	this.name = name
	this.age  = age
	this.sex  = sex
	this.getName = function(){
		console.log(this.name)
	}
}
// o = Person("wanger", 18, "girl")
wanger   = new Person("wanger", 18, "girl")
zhangsan = new Person("zhangsan", 28, "boy")

//可以通過執行個體的constructor屬性檢視自己的構造函數
console.log(wanger.constructor)
console.log(wanger instanceof Person)

/* 
構造函數的缺點:
 構造函數方式主要是造成每個執行個體都會定義自己的方法,這樣會占用更多的記憶體
 */
// console.log(wanger.getName)
// console.log(zhangsan.getName)

/* 
 兩個執行個體相同的方法并不是同一個對象
 */
console.log(wanger.getName == zhangsan.getName)

           

運作結果:

(構造函數用new建立的執行個體,通路屬性中隻能通過

”執行個體+點+屬性“的方式,不能直接寫屬性名)

Python學習筆記:5.2.5 javascript面向對象
Python學習筆記:5.2.5 javascript面向對象
2.3.原型模式

構造函數的問題就是執行個體之間不能共享方法

函數對象原型Person.prototype

function Person(){
	
}
Person.prototype = {
	hello:function(){
		console.log("hello")
		console.log(this.name)
	}
}
person_1 = new Person()
person_2 = new Person()

person_1.name = "luxp"
person_2.name = "lisi"

person_1.hello()
person_2.hello()

function Person(name, age, sex) {
	this.name = name
	this.age  = age
	this.sex  = sex
	this.family = []
	this.say = function(){
		console.log("my name is "+this.name)
	}
}

wanger   = new Person("wanger", 18, "girl")
zhangsan = new Person("zhangsan", 28, "boy")

// 在原型上添加一個方法{}

Person.prototype.getName = function(){
	console.log(this.name)
}


console.log(wanger.say == zhangsan.say)
//還可以增加共同的屬性 - 相當于python的類屬性

Person.prototype.hands = 2
console.log(wanger.hands)

Person.prototype.getSex = function(){
	console.log(this.sex)
}

console.log(wanger.getSex())

//
//這樣設定,等于重寫了prototype

Person.prototype = {
	"getAge":function (){
		console.log(this.age)
	}
}

lisi = new Person("lisi", 38, "boy")
           

2.3.1.apply與call

call是函數對象的一個方法

通過call 可以指定函數内部的this對象

第一個參數是this指向的對象,後面通過逗号分隔傳遞多個參數

例如:Function.call(obj, args1,arg2,…)

function myFun(property){
	console.log(this)
	console.log(this.name)
	console.log(this[property])
}

var o1 = {
   name:"luxp",
   sex : "男"
}
		
var o2 = {
   name:"whh",
   sex : "女"
}

myFun.call(o1, "sex")
// myFun.call(o2, "sex")
           

運作結果:

Python學習筆記:5.2.5 javascript面向對象

apply也是是函數對象的一個方法

功能與call一樣,不同的是參數傳遞方式

第一個參數是this指向的對象,第二個是參數數組

例如:Function.apply(obj, [args1,arg2,…])

myFun.apply(o1, ["sex"])
// myFun.apply(o2, ["sex"])
           

運作結果:

Python學習筆記:5.2.5 javascript面向對象

2.3.1.原型繼承

function Person(name, age, sex) {
	this.hands = 2
	this.legs  = 2
	this.family  = []
	this.say = function(){
		console.log("my name is "+this.name)
	}
}

//子對象結構函數
function Man(name, age){
	this.name = name
	this.age  = age
	this.sex = "男"
	
}

//将原型指向到Person,即可繼承
Man.prototype = new Person()

//重寫原型方法
Man.prototype.say = function(){
		console.log("welcome to here")
	}

// 
wangwu = new Man("wangwu", 58)
zhangsan = new Man("zhangsan", 28)


function WoMan(name, age){
	this.name = name
	this.age  = age
	this.sex  = "女"
}

//将原型指向到Person
WoMan.prototype = new Person()
//重寫原型方法
WoMan.prototype.say = function(){
	console.log("hi,what can i do for you?")
}


cuihua = new WoMan("cuihua", 18)

/* 
 添加家庭成員
 */
wangwu.family.push("whife")

/* 
 尴尬的事情,同一個Man的對象,引用型屬性是互相共享的
 */
lisi = new Man("lisi", 28)
lisi.family.push("son")
// console.log(lisi.family)
           

運作結果:

Python學習筆記:5.2.5 javascript面向對象
Python學習筆記:5.2.5 javascript面向對象
Python學習筆記:5.2.5 javascript面向對象

在js裡,引用型屬性是互相共享的,是以當lisi往family屬性裡添加一個son值時,zhangsan的family屬性裡也多了一個son的值,明顯這是不合理的,是以才會有原型繼承的改進方法,看下一小節内容

Python學習筆記:5.2.5 javascript面向對象

2.3.2.原型繼承改進

/* 
 改進引用型值在各個執行個體間共享的問題
 */
function Person(name, age, sex,family) {
	this.name = name
	this.age  = age
	this.sex  = sex
	this.family = family
	this.say = function(){
		console.log("my family has "+this.family)
	}
}

function Man(name, age, sex){
	console.log(Man.prototype)
	console.log(Man.prototype.constructor)
	//相當于python的super()執行
	// Person.call
	Man.prototype.constructor.call(this, name, age, sex, [])
}

Man.prototype = new Person()
wangwu = new Man("wangwu", 58)
wangwu.family.push("father")
lisi = new Man("lisi", 38)
lisi.family.push("wife")
           
Python學習筆記:5.2.5 javascript面向對象

練習1:

定義一個車的構造函數,然後再定義汽車,自行車的構造函數,汽車與自行車主要是動力不同,

輪子數量不一樣

三、課程小結

  • 學習了js的工廠模式
  • 學習了js的構造函數
  • 學習了js的原型模式