面向对象练习题
原型链机制
先画图
扩展一下:
基于constructor来检测数据类型:
constructor在类的原型上。证明当前实例属于这个类,那我就要检测当前实例的constructor是不是这个类。
function Fn(){
this.x=100;
this.y=200;
this.getX=function(){
console.log(this.x);
}
}
Fn.prototype.getX=function(){
console.log(this.x);
}
Fn.prototype.getY=function(){
console.log(this.y);
}
let f1=new Fn();
let f2=new Fn();
console.log(f1.getX===f2.getX)
console.log(f1.getY===f2.getY)
!!!永远都是顺着原型链去找
原型重定向
function fun(){
this.a=0;
tihs.b=function(){
alert(this.a);
}
}
fun.prototype={
b:function(){
this.a=20;
alert(this.a);
},
c:function(){
this.a=30;
alert(this.a);
}
}
console.dir(fun);
console.dir(fun.prototype);
let obj={ .. }
我们其实是新开了一个堆内存,存储了一些键值对;
让obj和那个堆内存地址进行关联,即让obj指向它;
细节以及有可能带来的问题
原型重定向 :
堆内存已无人占用,所以在空闲时会被销毁
重构类的原型:让原型指向一个新的堆内存
重定向后的堆内存中constructor属性可能会丢失掉;
(包括原有的属性和方法也有可能会丢失掉)
几道面试题
1.原型涉及
function c1(name){
if(name){
this.name=name;
}
}
function c2(name){
this.name=name;
}
function c3(name){
this.name=name || 'join';
}
c1.prototype.name='Tom'
c2.prototype.name='Tom'
c3.prototype.name='Tom'
console.dir(new c1());
console.dir(new c2());
console.dir(new c3());
console.log(new c1().name+new c2().name+new c3().name);
2.原型重定向(一)
function Fn(num){
this.x=this.y=num;
}
Fn.prototype={
x:20,
sum:function(){
console.log(this.x+this.y);
}
}
let f=new Fn(10);
console.log(f.sum===Fn.prototype.sum);
f.sum();
Fn.prototype.sum();
console.log(f.constructor);
*3.原型重定向(二)
初始的Fn.prototype:浏览器天生开辟的堆
Fn.prototype = new Fn 原型重定向:
在没有重定向之前,我是先new Fn,创建好之后才让原型指向我这个实例对象;new Fn的时候原型还没有重定向,这个时候原型还没有重定向
即初始的Fn.prototype不能销毁,因为被new Fn占用了。
所以这里就有一个技巧:
如果它之前的原型上有方法,如果我不希望这些方法被替换掉或者丢失掉,那么我们就让原型指向当前类的一个实例,这样原有原型上的方法就能被保留下来。
这是原型和原型链的特点,这是后台不具备的。
比如原型继承,子类的原型指向父类的实例。
function Fn(){
let a=1;
this.a=a;
}
Fn.prototype.say=function(){
this.a=2;
}
Fn.prototype=new Fn;
let f1=new Fn;
Fn.prototype.b=function(){
this.a=3;
}
console.dir(f1);
console.dir(f1.__proto__.__proto__.__proto__); // Object.prototype
console.dir(f1.__proto__.__proto__.__proto__.__proto__);
console.log('----------')
console.log(f1.a);
console.log(f1.prototype);
console.log(f1.b)
console.log(f1.hasOwnProperty('b'));
console.log('b' in f1);
console.log(f1.constructor === Fn);
原型重定向之后开辟的实例跟之前的已经不一样了(但是最后会回归到Object.prototype)
4.扩展方法
Number.prototype.plus=function(number){
// if(typeof number !== 'number' || number instanceof Number){
// return
// }
if(!(typeof number === 'number' || number instanceof Number)){
return;
}
return this+number;
}
let n=5;
let m=n.plus(10);
console.log(n);
console.log('----------');
console.log(m);
// 升级版
(function(){
function checkX(x){
x=Number(x);
return isNaN(x)?0:x;
}
function plus(x){
x=checkX(x);
return this + x;
}
function minus(x){
x=checkX(x);
return this-x;
}
Number.prototype.plus=plus;
Number.prototype.minus=minus;
})();
let n=5;
let m=n.plus(10).minus(3);
console.log(n);
console.log('----------');
console.log(m);
只传n,什么都不传
传0,n比m大什么结果
负数 小数 非有效数字……