1.使用点语法完成默认值设置和新值替换
利用的是同一对象中相同属性名后面的会覆盖前面的原理
function fun (params) {
let config = {
name: '张三',
age: 18
}
config = {...config, ...params}
return config
}
console.log(fun({age: 20})) //name: '张三', age: 20
2.使用解构语法来分解一个对象
let user = {
name: '张三',
age: 18
}
let {name, age} = user //必须是一个对象才行
console.log(name, age) //张三 18
3.使用解构语法完成默认配置对象与合并
//这里的options一定要先赋值成一个对象,否则不能使用解构
function createDom (options = {}) {
let { width=200, height=200, backgroundColor="blue" } = options
const div = document.createElement("div")
div.style.width = width + 'px'
div.style.height = height + 'px'
div.style.backgroundColor = backgroundColor
document.body.appendChild(div)
}
//传参就用参数,不传就用默认的
createDom({width: 500})
4.对象的增删操作
let obj = {
name: '张三'
}
obj.age = 18
console.log(obj) //{name: 张三, age: 18} 增
delete obj.age
console.log(obj) //{name: 张三} 删
5.查看对象原型中是否含有某个属性
let user = {
name: '张三'
}
let age = {
age: 18
}
console.log(user.hasOwnProperty('age')) //查自己
Object.setPrototypeOf(user,age) //改变自己的上级
console.log('age' in user) //查自己和上级
6.使用assign来将两个对象合并为一个对象
function merge (params) {
let options = {
size: 100
}
let newMerge = Object.assign(options, params)
return newMerge
}
console.log(merge({name: '大小', size: 200}))
7.浅拷贝与深拷贝
浅拷贝就是普通的赋值,一旦拷贝的对象里面还有一个对象,那么新的对象与旧的会共用一个地址值,一旦发生改变就会都改变。
而深拷贝就会重新定义一块内存地址,这样就只会改变目标对象而不是全改
let obj = {
name: "张三",
user: {
name: "李四"
},
data: []
};
function copy(object) {
let obj = object instanceof Array ? [] : {};
for (const [key, value] of Object.entries(object)) {
obj[key] = typeof value == "object" ? copy(value) : value
}
return obj
}
let res = copy(obj);
res.data.push("abc");
console.log(JSON.stringify(res, null, 2))
console.log(JSON.stringify(obj, null, 2))
8.工厂函数
function fun (name, age) {
return {
name,
age,
showAge () {
console.log(`${name}的年龄是${age}`)
}
}
}
let zs = fun ('张三', 18)
let lisi = fun ('李四', 28)
console.log(zs) //{name: "张三", age: 18, showAge: ƒ}
console.log(lisi) //{name: "李四", age: 28, showAge: ƒ}
lisi.showAge() //李四的年龄是28
9.抽象
当函数内部有些东西不希望用户发现或改变时就需要把它抽象化
function User (name, age) {
let info = {name, age} //封装成变量而已
let showInfo = function () {
return age >= 18 ? '成年' : '未成年'
}
this.show = function () {
console.log(`${info.name}是个${showInfo()}`)
}
}
let zs = new User('张三', 18)
console.log(zs)
zs.show()
10.对象的属性特征
不带S就是查看一个(属性要加上""), 带S就是查看所有
let obj = {
name: '张三',
age: 18
}
console.log(JSON.stringify(Object.getOwnPropertyDescriptor(obj, "name"), null, 2))
console.log(JSON.stringify(Object.getOwnPropertyDescriptors(obj), null, 2))
11.修改对象的属性特征
let obj = {
name: '张三',
age: 18
}
Object.defineProperties( obj, {
name: {
value: '张三',
writable: false, //是否可以重新改
enumerable: false, //是否可以枚举
configurable: false //是否可以设置
},
age: {
value: '18',
writable: false,
enumerable: false,
configurable: false
}
})
console.log(JSON.stringify(Object.getOwnPropertyDescriptors(obj), null, 2))
12.系统自带的控制增删改属性的API和判断是否可以增删改
let obj = {
name: '张三',
age: 18
}
Object.preventExtensions(obj) //这样就不能往里面增删改
if(Object.isExtensible(obj)){ //会判断是否可以增删改并返回布尔值
obj.gender = '男'
}
console.log(obj)
13.封闭对象
跟上面那个一样
let obj = {
name: '张三',
age: 18
}
// Object.seal(obj)
if(!Object.isSealed(obj)){
obj.gender = '男'
}
console.log(obj)
14.冻结
跟上面一样,但范围更广
let obj = {
name: '张三',
age: 18
}
// Object.freeze(obj)
if(!Object.isFrozen(obj)){
obj.gender = '男'
}
console.log(obj)
15.访问器保护数据
当数据被调用时会触发get方法,
当数据被操作时会触发set方法
let obj = {
data: {name: '张三',gender: '男',age: 18},
set age (value) {
if( typeof value!== 'number' || value<10 || value>100){
throw new Error ('大胆妖孽,竟然班门弄斧,大威天龙')
}
this.data.age = value
},
get age () {
return this.data.age + '岁'
}
}
obj.age = 30
console.log(obj.age)
16.使用代理来完成积成算法
function factorial (num) {
return num === 1 ? 1 : num * factorial (num-1)
}
let proxy = new Proxy (factorial,{
apply (fun, obj, args) { //factorial,window,传过来的参数
console.time("run")
fun(args)
console.timeEnd("run")
}
})
proxy.apply(this, [5])
17.通过代理完成双向数据绑定
<input type="text" v-model="title">
<input type="text" v-model="title">
<p v-bind="title">同样发生改变</p>
<script>
// "use strict"
function View () {
let proxy = new Proxy (
{},
{
get (obj, property) {},
set (obj, property, value) {
document.querySelectorAll(`[v-model=${property}]`)
.forEach (item => {
item.value = value
})
document.querySelectorAll(`[v-bind=${property}]`)
.forEach (item => {
item.innerHTML = value
})
}
})
this.init = function () {
const els = document.querySelectorAll("[v-model]")
els.forEach (item => {
item.addEventListener("keyup", function () {
proxy[this.getAttribute("v-model")] = this.value
})
})
}
}
new View().init()
18.使用代理完成表单验证
<style>
.error{
border: 5px red solid;
}
</style>
<input type="text" validate rule="max:12,min:3">
<input type="text" validate rule="max:3,isNumber">
<script>
//验证处理类
class Validate {
max (value, len) {
return value.length <= len
}
min (value, len) {
return value.length >= len
}
isNumber (value) {
return /^\d+$/.test(value)
}
}
function makeProxy (target) {
return new Proxy (target, {
get (target, key) {
return target[key]
},
set (target, key, el) {
const rule = el.getAttribute("rule")
const validate = new Validate()
let state = rule.split(",").every(rule => {
const info = rule.split(":")
return validate[info[0]](el.value, info[1])
})
el.classList[state ? "remove":"add"]("error")
}
})
}
const proxy = makeProxy (document.querySelectorAll("[validate]"))
proxy.forEach ((item, i) => {
item.addEventListener("keyup", function(){
proxy[i] = this
})
})
19.JSON序列化和反序列化
序列化
第一个参数为要序列化的对象,
第二个参数为被传递的具体属性,null就是全部传递
第三个参数就是前面有几个空格
反序列化
第一个参数为要反序列化的JSON
第二个参数可以是个函数
let obj = {
name: '张三',
age: 18,
gender: {
zs_gender: '男' //对象中的对象不会被序列化!!!
}
}
let json = JSON.stringify(obj, ["name", "gender"], 2)
console.log(json)
let newobj = JSON.parse(json, (key, value) => {
if(key === "name"){
value = `他的名字叫${value}`
}
return value
})
console.log(newobj)