提问者:本人遇到的前端面试问题,请高手帮忙解决。其他有兴趣的同学也可以来看看能不能答对。varA=function(){};A.prototype={};varB={};console.log(A.constructor);//Functionconsole.log(B.constructor);//Objectvara=newA();A.prototype={};varb=newA();b.constructor=A.constructor;console.log(a.constructor==A);//falseconsole.log(a.constructor==b.constructor);//falseconsole.log(ainstanceofA);//falseconsole.log(binstanceofA);//true看不懂这两个console.log的结果,我觉得应该是console.log(ainstanceofA);//trueconsole.log(binstanceofA);//true但在浏览器中试了一下,确实是上面的答案,求解答,先谢谢了。答一:首先说明instanceof和constructor没有半钱关系,所以主题有效代码如下:varA=function(){};A.prototype={};//这里的空对象就是对象1vara=newA();A.prototype={};//这里的空对象就是对象2varb=newA();console.log(ainstanceofA);//falseconsole.log(binstanceofA);//true特别注意我加的两个注释,对象1和对象2不是同一个对象!再解释一下instanceof。具体可以参考ECMAScript官方文档和IBM开发者社区的解释。简而言之,instanceof操作符返回的是A的原型对象是否存在于a的原型链中。那么上面的代码可以用下面的图来说明:可以看到A的原型对象在a的原型链上是不存在的,所以console.log(ainstanceofA);//false,而A的原型对象b存在A的原型对象,所以console.log(binstanceofA);//true答案2:1)ainstancofA检查a的原型链中是否存在A.prototype2)每个js对象都有一个proto属性(标准表示[[prototype]])proto是普通对象的隐式属性。new时,会指向原型指向的对象;新对象没有原型属性。proto其实是一个对象的一个??属性,prototype是属于构造函数的一个属性。Prototype指向一个实体对象,即它有一个proto属性;对象的原型访问链是通过原型属性的串联构造的。起点是一个具体的对象,终点是Object.prototype。proto([[prototype]]))为null3)constrcutor是对象的构造函数对象,存在于原型对象(prototypeobject)中。只要不再次复制原型对象,构造函数就指向构造函数本身。默认构造函数是functionobject()那么我们来分析一下题目//和functionA(){}是一样的,只是原来的题目通过匿名函数表达式生成了一个函数对象varA=function(){};A代替的函数声明。prototype={};//重新复制此时构造函数对象A的prototype属性,constructor属性没有了,此时console.log(A.prototype.constructor==A);//false,console.log(A.prototype.constructor);//functionObject()//如果A.prototype={}不执行;thenconsole.log(A.prototype.constructor==A);//true,console.log(A.prototype.constructor);//functionA()//第二次出现A.prototype={};有一个直观的区别,我们添加如下语句A.prototype={first:'first'};varB={};console.log(A.constructor);//Function函数的构造函数是functionFunction()console.log(B.constructor);//Object普通对象的构造函数为functionObject()vara=newA();//新建一个对象a,//此时执行console.log(a.constructor);//functionObject()console.log(a.constructor==A);//falseconsole.log(ainstanceofA);//truea.__proto__指向A构造函数的原型对象Object{first:"first"}A.prototype={};//修改构造函数A的prototype属性,与第一次出现的不同,添加如下语句A.prototype={second:"second"};//A的prototype属性的值这个时候构造函数和定义A的时候是不一样的。//这个时候我们调用//console.log(a.constructor==A);//console.log(ainstanceofA);//会发生什么?console.log(a.constructor==A);//falseconsole.log(ainstanceofA);//falseconsole.log(a.__proto__);//对象{first:"first"}与当前A.prototype不同,也就是说,构造函数原型的改变不影响创建的对象,//这个原理同varb=2,a=b;console.log(a);console.log(b);b=3;;console.log(a);控制台日志(b);同样console.log(a.constructor);//functionObject()console.log(A.constructor);//functionFunction()varb=newA();//创建一个新的对象B,基于修改后的A.prototypeconsole.log(b.__proto__);//Object{second:"second"}b.constructor=A.constructor;//原型链上的constructor属性此时不会被修改。其实就是给对象增加了一个名为constructor的普通属性,这个属性和原型上的constructor没有任何关系。//多说一句,在读取属性值或者调用方法的时候,会涉及到查找规则为原型链上的属性。设置属性不适用,直接给b添加属性(会有一些小的区别,不知道的可以参考javascriptP1445.1.2)//b.constructor是Functionconsole.log(a.constructor==A);//falsea.constructorisObjectconsole.log(a.constructor==b.constructor);//falseb.constructorisFunction//A.prototype->{second:"second"};//b.__proto__->Object{second:"second"}//a.__proto__->Object{first:"first"}console.log(ainstanceofA);//falseconsole.log(binstanceofA);//true答案3.第一个all,instanceof到底比较什么?instanceof比较构造函数的prototype属性(第二个参数)指向的原型对象是否能在实例的原型对象链中找到,找到则返回true,否则返回false;2.方法A的原型被篡改Object(A.prototype={})这一步之后,实例a.[[proto]]=functionA(){}.prototype!!//注意加粗的原型此时就变成了{}!而constructor是原型对象的一个??属性,所以a.constructor==functionObject(){}!!//{}根据找到A.[[proto]]=functionFunction(){}.prototype//A.constructor=functionFunction(){}//显然是A.constructor!=a.constructor;下一个比较一样明白答案4.构造函数挂在原型下面。当A.prototype={}时,构造函数被删除。所以a为假,b重置构造函数指向A,则b为真
