几道有意思的面向对象面试题

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方法的原型对象堆内存已经被浏览器再空闲时间释放掉了,因此会报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值