javascript面向对象
创建对象的方法
一、创建对象的方法
1、普通的创建方法
new Object()// 使用系统构造函数(构造器)
let obj = { // 字面量
name: "蒙娅",
sex: "20",
hero: function () {
console.log(`王者英雄${this.name}`)
}
}
obj.hero()
2、工厂函数
function createdfn(name, sex) {
let obj = new Object();//或者使用 let obj={}
obj.name = name
obj.sex = sex
obj.hero = function () {
console.log(`王者荣耀${name}`)
}
return obj
}
console.log(createdfn('刘备', 40))
createdfn('关羽', 50).hero()
console.log(createdfn('关羽', 50).hero === createdfn('刘备', 40).hero) // false 缺点造成内存的浪费
2、构造函数
1)构造函数是用new 来调用的,
2)所谓的构造函数,就是专门生成 "对象"的函数 ,提供模板,作为对象的基本结构
3)构造函数内部使用了this变量,对构造函数new运算符, 就能生成实力,并且this变量会绑定再实例对象上
4)instanceof 方法可以验证原型对象与实例之间的关系
function fun() {
return this
}
console.log(fun()) // window
console.log(new fun()) // fun {} 构造函数的this指向的当前实例
function Constructor(name, sex) {
this.name = 'name'
this.sex = sex
this.hero = function () {
console.log(`我是狗腿子${name}`)
}
}
console.log(new Constructor('西门庆', '18'))
console.log(new Constructor('西门庆', '18').hero() == new Constructor('潘金莲', '18').hero()) //true
console.log(new Constructor('西门庆', '18') instanceof Constructor) // true
let objUser = {}
// Constructor.apply(objUser,['武松',50])
Constructor.call(objUser, '武松', 50)
console.log(objUser) //{name: "name", sex: 50, hero: ƒ}
console.log(new Constructor('西门庆', '18')) == new Constructor('潘金莲', '18') //false 两个对象的实例地址是不同的,说明两个对象占用了两个空间的内存,跟工厂函数有一个缺陷
2、原型模式(prototyppe)
// function Prototypes(name, sex) {
// Prototypes.prototype.name = name
// Prototypes.prototype.sex = sex
// Prototypes.prototype.hero = function () {
// console.log(`我是狗腿子${name}`)
// }
// }
// Prototypes简化版本
function Prototypes(name, sex) {
Prototypes.prototype = {
constructor:Prototypes,
name: name,
sex: sex,
hero: function () {
console.log(`我是狗腿子${name}`)
}
}
}
console.log(new Prototypes('吕布', 35),'******')
console.log(new Prototypes('吕布', 35).name === new Prototypes('潘凤', 35).name) // true 说明都是引用同一个地址 同一个内存地址 prototype对象
// 1) prototype 模式验证方法
// 1.isPrototypeOf) 这个法用来判断,某个proptotype对象和某个实例之间的关系。
// 2.hasOwnProperty()每个实例对象都有一个hasOwnProperty)方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。
// 3.in运算符in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。in运算符还可以用来遍历某个色的所有属性。
let a = new Prototypes('吕布', 35)
console.log(Prototypes.prototype.isPrototypeOf(a)) // true a是原型创建的对象
console.log(a.hasOwnProperty('name')) //false
console.log("name" in a) //true
alert(a.constructor)
5、构造函数和原型组合模式(比较常见创建对象的方法)
function Parsent(name,hobby){
this.name=name;
this.hobby=hobby;
}
Parsent.prototype={
run:function(){
alert(`${this.name}在${this.hobby}`)
}
}
let bb =new Parsent('澜',['打龙','推塔'])
let cc =new Parsent('伽罗',['打龙','推塔'])
bb.run()
cc.run()
二、匿名函数匿名函数(没有函数名字的函数)
//普通函数
function myFn() {
console.log('我是普通函数')
}
let fn2 = function () {
console.log('我是匿名函数')
}
fn2();
//匿名函数自调用
(function (name) {
alert(`我是匿名函数自调用${name}`)
})('hello')
三、闭包
1.常见的方式是在函数内部创建另一个函数
2.闭包的第一个用途:通过闭包可以访问局部变量
3.闭包的第二个用途:可以让这些变量的值始终保持在内存中
4.优点:可以把局部变量驻留在内存中,可以避免使用全局变量;全局变量在复杂程序中会造成许多麻烦(比如命名冲突,垃圾回收等),所以推荐使用私有的,封装的局部变量。而闭包可以实现这一点。
5.缺点:由于闭包里作用域返回的局部变量资源不会被立刻销回收,所以可能会占用更多的内存:所以过度使用闭包会导致性能下降;
// 常见写法
function fn1() {
let name = '我是局部变量'
return function () {
console.log(name)
}
}
fn1()()
// 使用闭包实现累加
function gun() {
let a = 100;
return function () {
alert(a++)
}
}
1、调用方法一
// gun()(); gun()(); gun()() //100 这种方法调用每次都会初始化 a变量
2、调用方法二
//let f = gun() //这只会执行一次,后面调用都是执行内部的匿名函数
f(); //101
f(); //102
f(); //103
// f() = null //应及时 解除引用,否则占用更过内存
案例
// 循环中的匿名函数
let arr = []
function nice() {
for (var i = 0; i < 5; i++) {
arr[i] = function () {
return `元素${i++}`
}
}
return arr
}
console.log(nice()[0](), nice()[1](), nice()[2](), nice()[3]()) //5 5 5 5
let arr1 = []
function nice1() {
for (var i = 0; i < 5; i++) {
arr1[i] = (function () {
return `元素${i}`
})()
}
return arr1
}
console.log(nice1()[0], nice1()[1], nice1()[2], nice1()[3])//0 1 2 3
闭包中的this
可以使用对象冒充强制改变this的指向
将this赋值给一个变量,闭包访问这个变量
//闭包中的this
var type = '辅助'
let colsure = {
name: "关羽",
type: "坦克",
run: function () {
console.log(this.name)
},
hero: function () {
var that = this
return function () {
return `我是${this.type}`
// return `我是${that.type}` // 使用this 赋值改变this
}
}
}
colsure.run() // 关羽 this指向当前对象colsure
console.log(colsure.hero()()) // 我是辅助 // ·匿名函数的执行环境具有全局性,this通常是指向window的。
// 可以使用对象冒充强制改变this的指向
// 将this赋值给一个变量,闭包访问这个变量
console.log(colsure.hero().call(colsure), '使用call改变this指向') //我是坦克
// 模仿块级作用域
for (var m = 0; m < 5; m++) { };
console.log(m, '变量m');
(function () {
for (var K = 0; K < 5; K++) {
console.log(K)
}
})()
// console.log(K) //erro
四、继承
1、继承几种通用的方法
1)对象冒充(构造函数绑定) apply call 可以多个继承
function parsent(name) {
this.name = name
this.sun = function () {
return `我是装逼王${this.name}`
}
}
function parsenttwo() {
this.HP = '10000'
}
function Son(name) {
// parsent.call(this, name)
parsent.apply(this, [name])
parsenttwo.call(this)
console.log(this)
this.tick = '萌王'
}
let getvalue = new Son('龙傲天')
console.log(getvalue.name)
getvalue.sun()
2) 原型链继承
function PrototypeData() {
this.tile = "我是需要被继承的数据"
PrototypeData.prototype.runs = function () {
console.log('我是原型继承')
}
}
function inherit() { }
//inherit 现在的prototype指向的是PrototypeData的实例,inherit的prototype被继承
// 注意:原型继承不能继承多个类 ,后续新加入的类需要继承之后添加
inherit.prototype = new PrototypeData()
inherit.prototype.name = "在继承之后添加属性值"
let result = new inherit()
console.log(result)
result.runs()
3)混合模式(构造函数+原型)
function fn1(name) {
this.type = '动画',
this.hero = function () {
console.log(`我是${name}变成迪迦`)
}
}
fn1.prototype = {
activer: function () {
console.log('我是混合模式的继承')
},
sex: "20000"
}
function Fn2(name) {
fn1.call(this, name)
}
Fn2.prototype = new fn1()
let result2 = new Fn2('大古')
console.log(result2.type)
result2.hero()
result2.activer()
五、cookit
什么是cookit?
cookie是存储于访问者的计算机中的变量。每当同一台计算机通过浏览器请求某个页面时,就会发送这个
cookie。当用户下一次访问同一个页面时,服务器会先查看有没有上传留下的cookie资料,如果有就更根据
cookie里的资料判断访问者,发送特定的页面内容.
常见应用场景:自动登录,记住用户名..…
最初是用来在客户端和服务器端进行通信使用的,所以原则上应该在服务器运行环境下进行。目前大部分浏
览器可以在客户端生成和读取cookie数据(chrome不可以在客户端操作)
基本用法
document.cookit("name=我是Cookit协议")
alert(document.cookit)
//使用encodeURIComponent 编码 decodeURIComponent //解码
cookie可选参数:
expires = 时间:过期时间默认值为浏览器关闭后过期(即会话结束后)将expires设置为过去的时间可以删除cookie
path: 他指定了与cookie关联在一起的网页。默认值是在和当前网页同一目录的网页中有效。如果把path 设置为’/'那 么它对该网站的所有网页可见
domain: 设定cookie的有效域名,一般使用默认值,即绑定当前域名,本地测试无效
secure: 指定了网络上如何传输cookie.默认为普通http协议传输;若设置为安全的,将只能通过https安全协议才可以传输。
// cookit 函数封装
//1、普通创建cookit,太多而繁琐
document.cookit = 'name=刘备'
documen.cookit = 'hero=刺客'
//2、函数
function setCookit(key, values, expires, path) {
var times = new Date()
times.setDate(times.getDate() + expires) //设置多少天后过去
documen.cookit = `${key}=${value};expires=${times};path=${path}`
}
// setCookit('sex', '男', 10, '\/')
// 注意:cookie的限制:
// ·数量(20 - 50,不同浏览器有差异),大小有限(4k)
// ·有些数据不适合使用cookie保存,比如银行卡号等重要的信息
六、JSON
1、基本用法
// JSON.parse:解析
// JSON.stringify:序列化
let jsonValue = '{"name":"我是大哥大","hero":"杨戬","expires":"单词","domain":"hello"}'
let jsonObj=JSON.pase(jsonValue )
JSON.Stringify(jsonObj)
2、高阶用法
SON.parse高阶用法,参数二(选填):function
JSON.stringify高阶用法,参数二:[]或者function用法 参数三:number类型(key值空格缩进),字符串(key前面添加字符串)
// JSON.parse高阶用法,参数二(选填)
let setJson = JSON.parse(jsonValue, function (key, value) {
if (key != 'domain') {
return value
}
})
console.log(setJson) //{name: "我是大哥大", hero: "杨戬", expires: "单词"}
// JSON.stringify高阶用法,参数二:[]或者function用法 参数三:number类型(key值空格缩进),字符串(key前面添加字符串)
let jsonObj = { "name": "我是大哥大", "hero": "杨戬", "expires": "单词", "domain": "hello" }
let setStringify = JSON.stringify(jsonObj, ['name', 'expires'])
console.log(setStringify) //'{"name":"我是大哥大","expires":"单词"}'
let setvalues = JSON.stringify(jsonObj, function (key, value) {
if (key != 'domain') {
return value
}
}, '20')
console.log(setvalues) //'{"name":"我是大哥大","hero":"杨戬","expires":"单词"}'
// {
// 20"name": "我是大哥大",
// 20"hero": "杨戬",
// 20"expires": "单词"
// }