面向过程与面向对象
面向过程:
- 打开冰箱门
- 把大象装进去
- 关上冰箱门
面向对象:
- 大象
- 冰箱
- 隐藏对象
javaScript是一种基于对象(object-based)的语言
类与对象
类(calss) 是对象(object)的模板,定义了同一组对象共有的属性和方法。
ES5中的类与继承
// 定义类
function People (name, age) {
//实例属性
this.name = name;
this.age = age;
}
//实例方法
People.prototype.showName = function () {
console.log('我的名字是'+this.name);
}
//静态属性
People.count = 0
// 静态方法
People.getCount = function () {
// this 静态方法中的this指向类本身,而不是实例 console.log(this) //undefined
return People.count
}
ES5中实现继承: 构造函数继承:只能继承父类的属性,继承不了父类的方法
//父类
function Animal (name) {
this.name = name
}
Animal.prototype.showName = function () {
console.log('名字是:', this.name);
}
// z子类
function Dog (name, color) {
Animal.call(this, name) //继承实例属性
this.color = color
}
let d1 = new Dog('wangcai', 'yellow')
console.log(d1.showName(), 'dddd'); // d1.showName is not a function
原型继承: 只能继承方法,继承不了父类的属性
//父类
function Animal (name) {
this.name = name
}
Animal.prototype.showName = function () {
console.log('名字是:', this.name);
}
// z子类
function Dog (name, color) {
// Animal.call(this, name) //继承实例属性
this.color = color
}
Dog.prototype = new Animal() //继承父类方法
Dog.prototype.constructor = Dog //修正constructor
let d1 = new Dog('wangcai', 'yellow')
console.log(d1.showName(), 'dddd'); // 名字是: undefined
组合式继承:
//父类
function Animal (name) {
this.name = name
}
Animal.prototype.showName = function () {
console.log('名字是:', this.name);
}
// z子类
function Dog (name, color) {
Animal.call(this, name) //继承实例属性
this.color = color
}
Dog.prototype = new Animal() //继承父类方法
Dog.prototype.constructor = Dog //修正constructor
let d1 = new Dog('wangcai', 'yellow')
console.log(d1.showName()); // 名字是: wangcai
ES6中定义类:
// ES6中的类
class People {
constructor(name, age) {
this.name = name
this.age = age
}
showName() {
console.log('我的名字是'+this.name)
}
}
let p1 = new People('a', 18)
ES6继承:extends
class People {
constructor(name, age) {
this.name = name
this.age = age
}
showName() {
console.log('我的名字是'+this.name)
}
}
let p1 = new People('a', 18)
// console.log(p1)
class Coder extends People {
constructor(name, age, company) {
super(name, age)
this.company = company
}
showCompany() {
console.log('我的公司是'+this.company)
}
}
let c1 = new Coder('b', 20, 'baidu')
console.log(c1.showName());
在class内部最顶层定义属性,get,set
class People {
constructor(name, age) {
this.name = name
this.age = age
this._sex = '-1'
}
// 在class内部最顶层定义属性
get sex () {
return this._sex
}
set sex (val) {
this._sex = val
}
showName() {
console.log('我的名字是'+this.name)
}
// 静态方法
static getCount() {
return 5
}
}
// 静态属性
People.count = 9
Symbol
- 一种新的原始数据类型
- 声明方式
- 应用场景
let s1 = Symbol()
let s2 = Symbol()
console.log(s1 === s2) // false
let s1 = Symbol('s111')
let s2 = Symbol('s222')
console.log(s1 === s2) // false
Symbol for: 全局环境
let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
console.log(s1 === s2) //true
const s1 = Symbol('foo')
console.log(Symbol.keyFor(s1)) // undefined
const s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s2)) // foo
Object.getOwnPropertySymbols(xxx): 只能获取到Symbol定义的key Reflect.ownkeys(xxx):可以获得普通属性和Symbol定义的key
应用场景:
const shapeType ={
triangle:Symbol(),
circle:Symbol()
}
function getArea(shape){
let area = 0
switch(shape){
case shapeType.triangle:
area = 1
break
case shapeType.circle:
area = 2
break
}
return area
}
Set
- 一种新的数据结构
- 常用方法
- 增加:add
- 删除:delete
- 清空 clear
- 是否存在某一个值:has
- 大小: size
let s = new Set([1,3,3,4])
- 遍历
s.forEach(item => console.log(item))
for(let item of s){
console.log(item)
}
for(let item of s.keys()){
console.log(item)
}
for(let item of s.values()){
console.log(item)
}
for(let item of s.entries()){
console.log(item[0],item[1])
}
- 应用场景
//数组去重:
let arr = [1,2,3,4,2,3]
let s = new Set(arr)
console.log(s)
// 合并去重
let arr1 = [1,2,3,4]
let arr2 = [2,3,4,5,6]
let s = new Set([...arr1,...arr2])
console.log([...s])//转换为数组
console.log(Array.from(s))
//求交集:
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))
console.log(result) //Set(3) {2, 3, 4}
// 求差集
let result2 = new Set(arr1.filter(item => !s2.has(item)))
WeakSet
- 只能够存储对象
- 不可以遍历
- 弱引用,并不会被垃圾回收机制(GC)考虑
let ws = new WeakSet()
ws.add({
name:'imooc'
})
ws.add({age:5})
ws.delete()
Map
- 一种新的数据结构(key可以是任意类型)
- 常用方法
- 增加:set
- 获取:get
- 删除:delete
- 大小:size
- 是否有: has
// 遍历 forEach
map.forEach((value,key)=>console.log(value,key))
// for of
for(let [key,value] of map){
consolelog(key,value)
}
for(let key of map.keys()){
consoel.log(key)
}
for(let value of map.values()){
consoel.log(value)
}
for(let [key,value] of map.entries()){
consoel.log(key,value)
}
WeakMap
- key 必须是引用数据类型
- 不可以遍历
- 弱引用
字符串的扩展
正则表达式的扩展
- i 忽略大小写修饰符
- g 全局修饰符
- m 多行修饰符
- y 粘连修饰符 const str = 'aaa_aa_a'
const reg1 = /a+/g // 每次匹配剩余的 const reg2 = /a+/y // 剩余的第一个开始匹配
数值的扩展
// 十进制 -> 二进制
const a = 5 // 101
console.log(a.toString(2)) // 101
// 二进制 ->十进制
const b = 101
console.log(parseInt(b,2)) // 把b当做一个2进制的数去转化
ES6
-
0B 二进制
-
0O 八进制
-
Number.isFinite // 判断一个数是不是有限的
-
Number.isNaN
-
Number.isInteger //是否是一个整数
-
Math.pow(2,53) // 整数的最大值 2的53次方,最小值 负2的53次方
-
Math.sign(5) //1
-
Math.sign(-5) //-1
-
Math.sign(0) //0
-
Math.sign(NaN) //NaN
代理Proxy
- ES5 defineProperty
let obj = {}
let newVal = ''
Object.defineProperty(obj, 'name', {
get () {
console.log('get');
return newVal
},
set (val) {
console.log('set', val);
newVal = val
}
})
obj.name = 'newEs'
console.log(obj.name) //newEs
- ES6 proxy
//基础用法
let obj = {}
let p = new Proxy(obj, {})
obj.name = 'es6 proxy'
console.log(obj.name) //es6 proxy
for (let key in obj) {
console.log(key,':key'); //name :key
}
- get
let arr = [7, 8, 9]
arr = new Proxy(arr, {
get (target, prop) {
console.log(target, prop);
return prop in target ? target[prop] : 'error'
}
})
console.log(arr[1],'===='); // 8
let dict = {
'hello': '你好',
'world': '世界'
}
dict= new Proxy(dict, {
get (target,prop) {
return prop in target ? target[prop] : prop
}
})
console.log(dict['world'],'====dict'); //世界
- set
let arr = []
arr = new Proxy(arr, {
set (target, prop, val) {
if (typeof val === 'number') {
target[prop] = val
return true
} else {
return false
}
}
})
arr.push(5)
arr.push(6)
console.log(arr[0]); //5
- has
let range = {
start: 1,
end:5
}
range = new Proxy(range, {
has (target, prop) {
return prop >= target.start && prop <= target.end
}
})
console.log(2 in range); //true
- ownKeys
let obj = {
name: 'imooc',
[Symbol('es')]:'es6'
}
console.log(Object.getOwnPropertyNames(obj)) // [name]
console.log(Object.getOwnPropertySymbols(obj)) // [Symbol(es)]
console.log(Object.keys(obj)) // ['name']
for (let key in obj) {
console.log(key); //name
}
let userInfo = {
userName: 'heiheihei',
age: 34,
_password:'123'
}
userInfo = new Proxy(userInfo, {
ownKeys (target) {
return Object.keys(target).filter(key => !key.startsWith('_'))
}
})
for (let key in userInfo) {
console.log(key); //userName,age
}
console.log(Object.keys(userInfo));/ ['userName', 'age']
- 综合案例
let user = {
userName: 'heiheihei',
age: 34,
_password:'123'
}
user = new Proxy(user, {
get (target, prop) {
if (prop.startsWith('_')) {
throw new Error('不可访问')
} else {
return target[prop]
}
},
set (target, prop, val) {
if (prop.startsWith('_')) {
throw new Error('不可访问')
} else {
target[prop] = val
return true
}
},
// 拦截删除
deleteProperty (target, prop) {
if (prop.startsWith('_')) {
throw new Error('不可删除')
} else {
console.log(prop,target[prop],':prop');
delete target[prop]
return true
}
},
ownKeys (target) {
return Object.keys(target).filter(key => !key.startsWith('_'))
},
})
console.log(user.age); //34
console.log(user._password) //3-12.js:124 Uncaught Error: 不可访问
user._password = 'xx'
try {
delete user._password
} catch (e) {
console.log(e.message);
}
console.log(user._password,'====dddd');
for (let key in user) {
console.log(key,':====key');
}
- apply 拦截函数调用
let sum = (...args) => {
let num = 0
args.forEach(item => {
num += item
})
return num
}
sum = new Proxy(sum, {
apply (target,ctx,args) {
return target(...args)*2
}
})
// console.log(sum(1,2));// 6
// console.log(sum.call(null,1,2,3));// 12
console.log(sum.apply(null,[1,2,3]));// 12
- construct 拦截new
let User = class {
constructor(name) {
this.name = name
}
}
User = new Proxy(User, {
constructor (target, args, newTarget) {
return new target(...args)
}
})
console.log(new User('imm'));
小结
| 拦截器 | 作用 |
|---|---|
| get | 拦截对象属性的读取,比如proxy.foo和proxy['foo'] |
| set | 拦截对象属性的设置,返回一个布尔值,比如proxy.foo = v或proxy['foo'] = v |
| has | 拦截propKey in proxy的操作,返回一个布尔值 |
| ownKeys | 拦截Object.getOwanPropertyNames(proxy)、Object.getOwanPeopertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组 |
| deleteProperty | 拦截delete proxy[propKey]的操作,返回一个布尔值 |
| apply | 拦截函数的调用,call和apply操作 |
| construct | 拦截new命令,返回一个对象 |
Reflect
-
将Object属于语言内部的方法放到Reflect上
-
修改某些Object方法的返回结果,让其变得更合理
-
让Object操作变成函数行为
-
Reflect对象的方法与proxy对象的方法一一对应
-
改造案例
try {
Object.defineProperty()
} catch (e) { }
if (Reflect.defineProperty()) { // boolean
}
console.log('assign' in Object) //true
console.log(Reflect.has(Object, 'assign')) //true
let user = {
userName: 'heiheihei',
age: 34,
_password:'123'
}
user = new Proxy(user, {
get (target, prop) {
if (prop.startsWith('_')) {
throw new Error('不可访问')
} else {
// return target[prop]
return Reflect.get(target, prop)
}
},
set (target, prop, val) {
if (prop.startsWith('_')) {
throw new Error('不可访问')
} else {
// target[prop] = val
Reflect.set(target,prop,val)
return true
}
},
// 拦截删除
deleteProperty (target, prop) {
if (prop.startsWith('_')) {
throw new Error('不可删除')
} else {
// console.log(prop,target[prop],':prop');
// delete target[prop]
Reflect.deleteProperty(target,prop)
return true
}
},
ownKeys (target) {
// return Object.keys(target).filter(key => !key.startsWith('_'))
return Reflect.ownkeys(target).filter(key => !key.startsWith('_'))
},
})