本文是學習陸老師的《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)
運作結果:

練習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屬性沒有變化)
淺拷貝運作結果:(obj的屬性改變,obj_2的也發生改變)
練習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)
運作結果:
** 練習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)
}
}
運作結果:
練習九:
注冊使用者要求: 不能含有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建立的執行個體,通路屬性中隻能通過
”執行個體+點+屬性“的方式,不能直接寫屬性名)
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")
運作結果:
apply也是是函數對象的一個方法
功能與call一樣,不同的是參數傳遞方式
第一個參數是this指向的對象,第二個是參數數組
例如:Function.apply(obj, [args1,arg2,…])
myFun.apply(o1, ["sex"])
// myFun.apply(o2, ["sex"])
運作結果:
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)
運作結果:
在js裡,引用型屬性是互相共享的,是以當lisi往family屬性裡添加一個son值時,zhangsan的family屬性裡也多了一個son的值,明顯這是不合理的,是以才會有原型繼承的改進方法,看下一小節内容
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")
練習1:
定義一個車的構造函數,然後再定義汽車,自行車的構造函數,汽車與自行車主要是動力不同,
輪子數量不一樣
三、課程小結
- 學習了js的工廠模式
- 學習了js的構造函數
- 學習了js的原型模式