2020.9.18陈悦玲

防扩展
什么是防扩展?
禁止添加新属性,相当于将对象的extensible:false
设置防扩展
Object.preventExtensions(obj)
让一个对象变的不可扩展,也就是永远不能再添加新的属性,禁止强行给当前对象添加新属性
判断是否已禁止扩展
Object.isExtensible(obj)
问题:只能防扩展,不防删除

密封
什么是密封?
在兼具防扩展同时,又进一步禁止删除属性。但是,属性值还是可以修改的。在防扩展同时,禁止删除现有属性,相当于将每个属性的configurable:false,其他属性在修改特性时,不必反复修改configurable:false
密封对象
Object.seal(obj)
1. 如果使用了seal,就不用使用preventExtensions()了。因为seal中涵盖了防扩展的特点
2. 其实,seal就是自动将所有属性的configurable都自动改为了false。从此,只用seal,所有属性上的configurable:false,都可省略。默认都是关着的,false。一般的对象保护到密封级别就够了
判断是否密封
Object.isSealed(obj)
删除对象
delete obj.属性名
问题:实现一个JS类型,包含public属性和private属性
function Emp(eid,ename,salary,age){
this.eid=eid;
this.ename=ename;
this.salary=salary;
Object.defineProperties(this,{
id:{writable:false},
salary:{enumerable:false},
_age:{
writable:true,
enumerable:false
},
age:{
get:function(){return this._age;},
set:function(val){
if(val<18||val>65)
throw new Error('超出范围')
this._age=val;

},
enumerable:true
}
});
this.age=age;
// 防篡改:密封
Object.seal(this);
}
var emp=new Emp()
emp.age=20
emp.eid=101
emp.salary=30000
emp.ename="dingding"

冻结
什么是冻结?
即不能添加新属性,又不能删除现有属性。甚至连属性值都不能修改。在密封同时,禁止修改所有属性的值,相当于将每个属性的writable:false
什么时候使用?
如果一个对象中所有属性值都不允许擅自修改。很多模块共同使用的对象,不能随意被一方篡改
冻结对象
Object.freeze(obj)
判断是否冻结
Object.isFrozen(obj);
冻结原理
不但禁止添加新属性,且自动修改所有configurable:false,且自动修改所有writable:false

六、Object.create()
提示:创建一个新的子对象,继承父对象
1. 什么时候使用?
即使没有构造函数妈妈,只有一个父对象,也想创建子对象,继承父对象
2. 使用(3件事)
前两件事,创建一个子对象,并让新子对象继承指定的父对象
var child=Object.create(father);
创建一个新的子对象,自动设置新的子对象的__proto__指向父对象,这样添加完的对象是没有任何自有属性的,只能用爹里的共有属性
第三件事,可以给孩子添加自有属性,但是必须以Object.defineProperties类似的语法添加属性
var child=Object.create(father,{
属性名:{
value: 属性值,
writable: true/false,
… : …,
},
… :{…}
});
3. Object.create()共做了3件事
1. 先创建一个新的子对象
2. 让新的子对象继承父对象
3. 为新的子对象添加自有属性
案例:使用Object.create()创建子对象,继承父对象,并添加自有属性
var father = {
bal: 1000000,
car: '宝马'
}
var child = Object.create(father, {
phone: {
value: 'iPhoneX',
writable: true,
enumerable: true
},
bao: {
value: 'LV',
writable: true,
enumerable: true
}
})
Object.seal(child)
console.log(child)
console.log(child.bal, child.car)
console.log(child.phone, child.bao)

六、call/apply/bind()
提示:都能替换函数执行时,函数内不想要的this
1. 什么时候使用?
只要函数中的this不是想要的,就可用call/apply/bind替换this指向的对象
2. 使用(两种情况)
1. 在函数执行时,临时替换一次this为想要的对象(call/apply)
要调用的函数.call(替换this的对象, 实参值列表)
fun.call(obj, 参数值列表)
提示:调用fun,替换fun中的this为obj,将参数值列表传递给fun
function calc(base,bonus1,bonus2){
console.log(${this.ename}的总工资是${base+bonus1+bonus2});
}
var lilei={ ename:"Li Lei"};

calc.call(lilei,10000,1000,2000);
在本次调用函数时,先替换this为call中第一个参数指定的对象。这里calc中的this被临时替换为了对象lilei。之后的实参列表一对一赋值给原函数的形参列表。比如:这里10000给base, 1000给bonus1,2000给bonus2
如果原函数要求的参数是多个参数单独传入,而给定的实参值列表却是一个数组时,就要用apply()替换call()
call做了三件事
1. 调用函数
2. 用call的第一个参数对象临时替换函数中的this这个对象
3. 将call从第二个参数开始的实参值传给正在调用的函数的形参变量
要调用的函数.apply(替换this的对象, [包含实参值的数组])
fun.apply(obj, 参数值数组)
对比 call
1. apply要求传入fun的参数必须放在数组中整体传入
2. apply可自动将数组打散为单个参数值分别传入
apply做了三件事
1. 调用函数
2. 用apply的第一个参数对象临时替换函数中的this这个对象
3. 将apply第二个保存多个实参值的数组,先打散,再按顺序逐个传给正在调用的函数的形参变量
2. 基于原函数,创建一个新函数副本,但永久绑定新函数中的this为指定的对象(bind)
var 新函数=原函数.bind(替换this的对象)
什么时候使用?
如果要替换this的函数,不是立刻执行,也不是只执行一次。bind()专门用于替换回调函数中的this。因为回调函数往往不是立刻执行,且不止执行一次
使用(2步)
1. 先基于原函数创建一个一模一样的新函数副本,永久绑定this为指定的新对象
var fun=原函数.bind(替换this的对象)
提示:暂时不要传递实参值,因为不是立刻调用,只是创建函数副本而已
var calc1=calc.bind(lilei);
2. 反复调用副本函数,而不再担心this错误。此时再传入必要的实参值列表
fun(实参值列表)
提示:fun2中的this早就被绑定为了想要的对象
calc1(10000, 1000,2000);
注意:此时虽然传入calc,但是this->lilei
对比 call/apply
call/apply只执行一次。且只临时绑定一次。而bind创建一个副本,且永久绑定,即使日后反复调用函数副本,this也不会丢失或错乱
bind做了两件事
1. 创建一个和原函数一模一样的副本
2. 永久替换this为指定的对象
永久绑定部分实参值
bind不但可以永久绑定this,而且还可永久绑定部分实参值
var fun=原函数.bind(替换this的对象, 实参值,…)
提示:创建一个和原函数功能完全一样的新函数,永久绑定新函数中的this为obj,永久绑定新函数中的部分参数为参数值列表中的值
var calc2=calc.bind(lilei,10000)
不但this被永久替换为了想要的对象,且第一个参数也被提前永久绑定成了想要的实参值
调用这个函数副本时,只要传剩余的参数即可
calc2(1000,2000);
其中this->lilei,base->10000
注意:被bind创建的函数中的this和绑定的变量,任何情况下不能再被call替换
问题:arguments可不可以通过认数组的原型对象当干爹来使用数组家的函数?
只要是数字下标的对象,都可以通过继承数组的原型对象来使用数组家的函数,其实,还可以使用.call()抢
Array.prototype.reduce.call(arguments,(prev,elem)=>prev+elem,0)
function show(arr){
console.log(Array.prototype.reduce.call(arguments,(prev,elem)=>prev+elem,0))
}
show(1,2,3,4,5)

标签

评论

this is is footer