本文是学习陆老师的《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的原型模式