面向对象编程
let user = {
name: "小孙吗",
grade: [
{ name: "js", score: 99 },
{ name: "docker", score: 76 }
],
average() {
let total = this.grade.reduce((t, l) => t + l.score, 0);
return `${this.name}的平均成绩是: ${total / this.grade.length}`;
}
};
// console.log(user);
console.log(user.average());
属性的基本操作方法
let user = {
name: "sss",
"my age": 18
};
console.log(user.name);
console.log(user["name"]);
console.log(user["my age"]);
for (const key in user) {
console.log(user[key]);
}
user.age = 19;
user.get = function() {
return `${this.name}的年龄是${this.age}`;
};
console.log(user.get());
delete user.age;
console.log(user.get());
- 点语法
- [‘我是各种字符串’]
- [‘我是变量’]
解构赋值新增特性
let user = { name: "ss", age: 18 };
const { name } = user;
console.log(name);
严格模式中解构的差异
严格模式必须加const
"use strict";
const { name, age } = { name: "sss", age: 23 };
console.log(name, age);
解构操作的简写形式
let name = "sss",
url = "www.bai";
let opt = { name, url };
console.log(opt);
多层对象的解构操作
let kk = {
name: "sss",
lesson: {
title: "javascript"
}
};
let { name, lesson: { title } } = kk;
console.log(name, title);
利用默认值解决undefined报错
let { width = 200, height = 100, backgroundColor = "red" } = options;
函数参数解构技巧
function hd(name, { sex, age }) {
console.log(name, sex, age);
}
hd("aaa", { sex: "男", age: 18 });
对象的添加删除
添加:
let aa = {};
aa.name = "aaa";
hd["age"] = 18;
删除:
delete aa.name;
对象与原型链属性检测实例
- 检查当前对象
a.hasOwnProperty(“s”) - 检查对象(包含原型链)
console.log(“url” in a);
计算属性与assign使用
- 可以动态设置对象的键名
- Object.assign(a,b);可以将两个对象合并
遍历操作以及对象的一些方法
Object.keys(ss) //获取键值
Object.values(ss) //获取value
Object.entries(ss) //获取整体信息以数组展现
遍历用for in
for of 遍历实现方法:
let hd = {
name: "ss",
year: "2010"
};
for (const [key, value] of Object.entries(hd)) {
console.log(value);
}
对象的浅拷贝多种操作方法
只能拷贝一层对象,对于对象内部套对象则不再适用。
1.let obj = { ...ss};
2.let obj = Object.assign({}, ss);
3.for (const key in ss) {
obj[key] = hd[key] + "111";
}
4.let cms = {
name: ss.name
};
深拷贝多层次分析
由于对象是引用存储的,所以当嵌套复制只会直接拷贝内存地址,改变子对象中的子对象,父对象中的子对象也会发生改变。
方法:
多层递归(数组只能实现一层)
一般借助各种库
let data = {
name: "sss",
user: {
name: "hdcms"
},
arr: []
};
function copy(obj) {
let res = obj instanceof Array ? [] : {};
for (const [k, v] of Object.entries(obj)) {
res[k] = typeof v == "object" ? copy(v) : v;
}
return res
}
let hds = copy(data);
hds.arr.push("abc");
console.log(JSON.stringify(hd, null, 2));
console.log(JSON.stringify(data, null, 2));
使用工厂函数创建对象
function user(name, age) {
return {
name,
age,
show() {
console.log(this.name + `-sss.com`);
},
info() {
console.log(`${this.name}的年龄是${this.age}`);
}
};
}
使用构造函数创建windows对象
系统会自动return 但是如果return了返回啥就是啥
ps:这不就是普通函数然后new时候让它有了return么
"use strict";
function User(name) {
this.name = name;
this.show = function() {
console.log(this);
// console.log(this.name);
};
// return this;
// return {};
}
面向对象的封装与抽象
利用let 使外部无法影响到内部,内部互相访问通过闭包来实现,这种方法就是抽象
function User(name, age) {
let data = { name, age };
let info = function () {
return data.age > 50 ? "老年" : "青年";
};
this.show = function () {
console.log(data.name + info());
};
}
对象属性的值
通过
Object.getOwnPropertyDescriptor(user, "name")
或
Object.getOwnPropertyDescriptors(user)
获取属性特征
{
"value": "aa",//值
"writable": true,//是否可写
"enumerable": true,//是否可遍历
"configurable": true //是否可被删除/可配置属性(设置以上属性)
}
设置属性:Object.definePropertie
批量设置:Object.defineProperties
Object.defineProperties(user, {
name: {
value: "sss",
writable: true,
enumerable: false,
configurable: true
},
age: {
value: "sss",
writable: true,
enumerable: true,
configurable: true
}
});
设置不允许添加属性API
// Object.preventExtensions(user);//设置
if (Object.isExtensible(user)) {//判断是否设置了不允许添加
user.site = "sss";
console.log(user);
}
封闭对象的API
Object.seal(user);//设置
if (!Object.isSealed(user)) {//检测是否封闭
user.site = "sss";
delete user.name;
}
冻结对象API特性(最常用)
只读:不允许添加修改以及对对象内部做一些设置
Object.freeze(user);
使用访问器保护数据
"use strict";
const user = {
data: { name: "sam", age: 10 },
set age(value) {
if (typeof value != "number" || value < 10 || value > 100) {
throw new Error("年龄格式错误");
}
this.data.age = value;
},
get age() {
return this.data.age + "岁";
}
};
使用访问器伪造属性操作
使用方便,修改无效
"use strict";
let Lesson = {
lists: [
{ name: "js", price: 100 },
{ name: "mysql", price: 212 },
{ name: "vue.js", price: 98 }
],
get total() {
return this.lists.reduce((t, l) => t + l.price, 0);
}
};
使用访问器批量设置属性
"use strict";
const web = {
name: "sss",
url: "aaa",
get site() {
return `${this.name}的网址是${this.url}`;
},
set site(value) {
[this.name, this.url] = value.split(",");
}
};
web.site = "开源产品,www.sss.com";
TOKEN的读写处理(可以自己在项目中尝试一下)
直接用点的形式来改写token处理逻辑(或者其他用途,访问器真不错哦)
"use strict";
//token
let Request = {
set token(content) {
localStorage.setItem("token", content);
},
get token() {
let token = localStorage.getItem("token");
if (!token) {
alert("请登录");
}
return token;
}
};
Request.token = "3248989239823kldskjklsd";
console.log(Request.token);
访问器的优先级(放在data中的方式以及私有化)
利用data隔绝、利用symbol使得data唯一
"use strict";
const DATA = Symbol();
const user = {
[DATA]: { name },
age: 10,
set name(value) {
this[DATA].name = value;
},
get name() {
return this[DATA].name;
}
};
user.name = "sss";
在class语法糖中定义访问器
"use strict";
const DATA = Symbol();
class User {
constructor(name, age) {
this[DATA] = { name, age };
}
get name() {
return this[DATA].name;
}
set name(value) {
if (value.trim() == "" || value.length > 20) {
throw new Error("用户名不合法");
}
this[DATA].name = value;
}
get age() {
return this[DATA].age;
}
set age(value) {
this[DATA].name = age;
}
}
什么是Proxy代理拦截
将整个对象代理给别人处理(类似找中介买房子)
内置函数参数:整个proxy、键(如果是数组就是索引)、值
"use strict";
const hd = { name: "sss" };
const proxy = new Proxy(hd, {
get(obj, property) {
// console.log(obj);
return obj[property];
},
set(obj, property, value) {
obj[property] = value;
return true;
}
});
console.log(proxy.name);
proxy.name = "aaa";
console.log(proxy.name);
console.log(proxy);
使用代理Proxy控制函数
参数:(函数、上下文、函数的参数)
function factorial(num) {
return num == 1 ? 1 : num * factorial(num - 1);
}
let proxy = new Proxy(factorial, {
apply(func, obj, args) {
console.time("run");
func.apply(this, args);
console.timeEnd("run");
}
});
proxy.apply({}, [1000]);
数组使用代理拦截操作
参数:(原数组、key)
const lessons = [
{
title: "媒体查询响应式布局",
category: "css"
},
{
title: "FLEX模型",
category: "css"
},
{
title: "MYSQL多表查询随意操作",
category: "mysql"
}
];
let proxy = new Proxy(lessons, {
get(array, key) {
const title = array[key].title;
const len = 10;
array[key].title =
title.length > len ? title.substr(0, len) + ".".repeat(3) : title;
return array[key];
}
});
双向绑定的实现
- 创建一个空对象用于存放数据
- 其他几个需要双向绑定的与这个空对象进行绑定
- 改变后将数据存放于对象中同时触发set(这里Vue用的是get与set)
- 将改变后的数据设置于其他绑定的模块
function View() {
let proxy = new Proxy(
{},
{
get(obj, property) {},
set(obj, property, value) {
// console.log(value);
// console.log(property);
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();
表单验证(这个自己封装一下封装好了在这写好地址)
"use strict";
class Validate {
max(value, len) {
return value.length <= len;
}
min(value, len) {
return value.length >= len;
}
isNumber(value) {
return /^\d+$/.test(value);
}
}
function ProxyFactory(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");
return true;
}
});
}
const proxy = ProxyFactory(document.querySelectorAll("[validate]"));
proxy.forEach((item, i) => {
item.addEventListener("keyup", function () {
proxy[i] = this;
});
});
JSON.stringify
参数:(需要转换的对象、需要保留的值(全部就是null)、首行缩进)
可以在对象中定义json默认返回哪些
let hd = {
title: "aa",
url: "sss.com",
teacher: {
name: "ddd"
},
toJSON: function () {
return {
title: this.title,
teacher: this.teacher.name
};
}
};
let json = JSON.stringify(hd, null, 2);
console.log(json);
JSON.parse中的参数
let ac = {
title: "aaa",
url: "sss.com",
teacher: {
name: "vvv"
}
};
let json = JSON.stringify(ac, null, 2);
console.log(json);
let obj = JSON.parse(json, (key, value) => {
if (key == "title") {
value = "[你好]-" + value;
}
return value;
});