1
let obj = {
2: 3,
3: 4,
length: 2,
push: Array.prototype.push
}
obj.push(1);
obj.push(2);
console.log(obj);
做这道题我们需要大概了解Array.prototype上的push方法是怎么处理的~
Array.prototype.push = function push(val){
this[this.length] = val; // 向数组末尾添加元素
this.length++; // 数组长度增加
return this.length; // 返回数组长度
}
回来看这道题
① obj.push(1)
:this->obj, this.length = 2, 即obj[2] = 1
; this.length++ ->3
② obj.push(2)
:this->obj, this.length = 3, 即obj[3] = 2
; this.length++ ->4
③ console.log(obj)
, obj中的元素被修改为了1和2,同时length属性值变为4。
2
a等于什么值会让下面条件成立
var a = ?;
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
小朋友,你是否有很多问号???
一个值能既=1,又=2,还=3,怎么可能会有这样的值?
别说,还真有。但确实不是一个单纯的基本类型值。
方案一:
既然a不是一个简单的基本类型值,若a是一个对象,对象与数字在做==比较时,必然会调用toString() / valueOf() 方法,我们就在这里做写文章,重写toString() / valueOf() 私有方法,不让它去原型上找方法了。
var a = {
i:0,
toString(){
return ++this.i;
}
}
做a==1
比较时,调用a对象的私有toString()方法( 方法中的this是a ),返回1(++i),则1 == 1返回true;
做a==2
比较时,调用a对象的私有toString()方法( 方法中的this是a ),返回2(++i),则2 == 2返回true;
做a==3
比较时,调用a对象的私有toString()方法( 方法中的this是a ),返回3(++i),则3 == 3返回true。
方案二: 数据劫持
只能劫持对象中的某个属性,每次获取a的值时把它劫持到,然后返回需要的值(返回啥,获取的值就是啥)
var i = 0;
Object.defineProperty(window,'a',{
get(){
return ++i;
}
})
第一次获取a的值,劫持到window对象上的i属性,返回1(++i)并赋值给a
第二次获取a的值,劫持到window对象上的i属性,返回2(++i)并赋值给a
第三次获取a的值,劫持到window对象上的i属性,返回3(++i)并赋值给a
注:这道题中只涉及到获取,即get()方法,在获取window.a时触发。如果涉及到设置window.a的值,则会触发set()方法。
3
function Fn(n,m) {
n=n||0;
m=m||0;
this.x = n;
this.y = m;
this.getX = function () {
console.log(this.x);
}
return n+m;
}
Fn.prototype.sum=function(){
console.log(this.x+this.y);
}
Fn.prototype={
getX:function(){
this.x+=1;
console.log(this.x);
},
getY:function(){
this.y-=1;
console.log(this.y);
}
};
let f1 = new Fn(10,20);
let f2 = new Fn;
console.log(f1.getX === f2.getX);
console.log(f1.getY === f2.getY);
console.log(f1.__proto__.getY === Fn.prototype.getY);
console.log(Fn.prototype.getX === f2.getX);
console.log(f1.constructor);
f1.getX();
Fn.prototype.getX();
f2.getY();
Fn.prototype.getY();
f1.sum();
第一件事:上图
① f1.getX === f2.getX
,f1和f2的实例对象上均有getX私有方法,因此返回false。
② f1.getY === f2.getY
,f1和f2的实例对象上均没有getY私有方法,因此通过__proto__找到原型上的公有方法,因此返回true。
③ f1.__proto__.getY === Fn.prototype.getY
,根据上图,可知两个getY是同一个方法,因此返回true。
④ Fn.prototype.getX === f2.getX
,原型上的getX是公有方法,实例上的getX是私有方法,不是同一个方法,返回false。
⑤ f1.constructor
,f1实例对象上没有constructor私有属性,通过原型链找到重定向后的原型对象,再通过__proto__找到Object.prototype上,其constructor属性值为Object。
⑥ f1.getX()
,f1上的私有getX方法执行,输出this.x的值。此时this->f1,f1.x->10
⑦ Fn.prototype.getX()
,重定向后的Fn原型上的getX方法执行,this->Fn.prototype,上面没有x属性(默认为undefined),+1之后值为NaN。
⑧ f2.getY()
,f2实例上没有getY私有方法,通过原型链向上查找到重定向的原型对象,执行getY方法,将this.y - 1。this->f2,f2的y属性值为0,-1之后值为-1。
⑨ Fn.prototype.getY()
,重定向后的Fn原型上的getX方法执行,this->Fn.prototype,上面没有x属性(默认为undefined),-1之后值为NaN。
⑩ f1.sum()
,f1上没有sum私有方法,通过原型链查找,由于重定向的原因,带有sum方法的原型对象堆内存已经被浏览器再空闲时间释放掉了,因此会报错。