function Person(name) { this.name = name}var p2 = new Person('king');console.log(p2.__proto__) //Person.prototypeconsole.log(p2.__proto__.__proto__) //Object.prototypeconsole.log(p2.__proto__.__proto__.__proto__) // nullconsole.log(p2.__proto__.__proto__.__proto__.__proto__)/ull后面没有了,报错console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)/ull后面没有了,报错console.log(p2.constructor)//Personconsole.log(p2.prototype)//undefined p2是实例,没有prototype属性console.log(Person.constructor)//Function 一个空函数console.log(Person.prototype)//打印出Person.prototype这个对象里所有的方法和属性console.log(Person.prototype.constructor)//Personconsole.log(Person.prototype.__proto__)// Object.prototypeconsole.log(Person.__proto__) //Function.prototypeconsole.log(Function.prototype.__proto__)//Object.prototypeconsole.log(Function.__proto__)//Function.prototypeconsole.log(Object.__proto__)//Function.prototypeconsole.log(Object.prototype.__proto__)/ull
这道义题目考察原型、原型链的基础,记住就可以了。
// afunction Foo () { getName = function () { console.log(1); } return this;}// bFoo.getName = function () { console.log(2);}// cFoo.prototype.getName = function () { console.log(3);}// dvar getName = function () { console.log(4);}// efunction getName () { console.log(5);}Foo.getName(); // 2getName(); // 4Foo().getName(); // 1getName(); // 1 new Foo.getName(); // 2new Foo().getName(); // 3new new Foo().getName(); // 3
输出结果:2 4 1 1 2 3 3
解析:
var F = function() {};Object.prototype.a = function() { console.log('a');};Function.prototype.b = function() { console.log('b');}var f = new F();f.a();f.b();F.a();F.b()
输出结果:
aUncaught TypeError: f.b is not a functionab
解析:
function Foo(){ Foo.a = function(){ console.log(1); } this.a = function(){ console.log(2) }}Foo.prototype.a = function(){ console.log(3);}Foo.a = function(){ console.log(4);}Foo.a();let obj = new Foo();obj.a();Foo.a();
输出结果:4 2 1
解析:
function Dog() { this.name = 'puppy'}Dog.prototype.bark = () => { console.log('woof!woof!')}const dog = new Dog()console.log(Dog.prototype.constructor === Dog && dog.constructor === Dog && dog instanceof Dog)
输出结果:true
解析:
因为constructor是prototype上的属性,所以dog.constructor实际上就是指向Dog.prototype.constructor;constructor属性指向构造函数。instanceof而实际检测的是类型是否在实例的原型链上。
constructor是prototype上的属性,这一点很容易被忽略掉。constructor和instanceof 的作用是不同的,感性地来说,constructor的限制比较严格,它只能严格对比对象的构造函数是不是指定的值;而instanceof比较松散,只要检测的类型在原型链上,就会返回true。
var A = {n: 4399};var B = function(){this.n = 9999};var C = function(){var n = 8888};B.prototype = A;C.prototype = A;var b = new B();var c = new C();A.n++console.log(b.n);console.log(c.n);
输出结果:9999 4400
解析:
function A(){}function B(a){ this.a = a;}function C(a){ if(a){this.a = a; }}A.prototype.a = 1;B.prototype.a = 1;C.prototype.a = 1; console.log(new A().a);console.log(new B().a);console.log(new C(2).a);
输出结果:1 undefined 2
解析:
function Parent() { this.a = 1; this.b = [1, 2, this.a]; this.c = { demo: 5 }; this.show = function () { console.log(this.a , this.b , this.c.demo ); }}function Child() { this.a = 2; this.change = function () { this.b.push(this.a); this.a = this.b.length; this.c.demo = this.a++; }}Child.prototype = new Parent();var parent = new Parent();var child1 = new Child();var child2 = new Child();child1.a = 11;child2.a = 12;parent.show();child1.show();child2.show();child1.change();child2.change();parent.show();child1.show();child2.show();
输出结果:
parent.show(); // 1 [1,2,1] 5child1.show(); // 11 [1,2,1] 5child2.show(); // 12 [1,2,1] 5parent.show(); // 1 [1,2,1] 5child1.show(); // 5 [1,2,1,11,12] 5child2.show(); // 6 [1,2,1,11,12] 5
这道题目值得神帝,他涉及到的知识点很多,例如this的指向、原型、原型链、类的继承、数据类型等。
解析:
Child
的构造函数原本是指向Child
的,题目显式将Child
类的原型对象指向了Parent
类的一个实例,需要注意Child.prototype
指向的是Parent
的实例parent
,而不是指向Parent
这个类。parent
是一个Parent
类的实例,Child.prorotype
指向的是Parent
类的另一个实例,两者在堆内存中互不影响,所以上述操作不影响parent
实例,所以输出结果不变;child1
执行了change()
方法后,发生了怎样的变化呢?Child.prototype
上的b数组,this.a会指向child1
的a属性,所以Child.prototype.b
变成了[1,2,1,11];this.a
和this.b
的指向与上一句一致,故结果为child1.a
变为4;child1
自身属性并没有c这个属性,所以此处的this.c
会指向Child.prototype.c
,this.a
值为4,为原始类型,故赋值操作时会直接赋值,Child.prototype.c.demo
的结果为4,而this.a
随后自增为5(4 + 1 = 5)。child2
执行了change()
方法, 而child2
和child1
均是Child
类的实例,所以他们的原型链指向同一个原型对象Child.prototype
,也就是同一个parent
实例,所以child2.change()
中所有影响到原型对象的语句都会影响child1
的最终输出结果。Child.prototype
上的b数组,this.a会指向child2
的a属性,所以Child.prototype.b
变成了[1,2,1,11,12];this.a
和this.b
的指向与上一句一致,故结果为child2.a
变为5;child2
自身属性并没有c这个属性,所以此处的this.c
会指向Child.prototype.c
,故执行结果为Child.prototype.c.demo
的值变为child2.a
的值5,而child2.a
最终自增为6(5 + 1 = 6)。function SuperType(){ this.property = true;}SuperType.prototype.getSuperValue = function(){ return this.property;};function SubType(){ this.subproperty = false;}SubType.prototype = new SuperType();SubType.prototype.getSubValue = function (){ return this.subproperty;};var instance = new SubType();console.log(instance.getSuperValue());
原文出处:原型&继承题目及内容解答