首页IT科技原型继承的优缺点(原型&继承题目及内容解答)

原型继承的优缺点(原型&继承题目及内容解答)

时间2025-07-21 06:26:08分类IT科技浏览3982
导读:这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助...

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

这道义题目考察原型、原型链的基础,记住就可以了。

2. 代码输出结果

// a function Foo () { getName = function () { console.log(1); } return this; } // b Foo.getName = function () { console.log(2); } // c Foo.prototype.getName = function () { console.log(3); } // d var getName = function () { console.log(4); } // e function getName () { console.log(5); } Foo.getName(); // 2 getName(); // 4 Foo().getName(); // 1 getName(); // 1 new Foo.getName(); // 2 new Foo().getName(); // 3 new new Foo().getName(); // 3

输出结果:2 4 1 1 2 3 3

解析:

Foo.getName(),Foo为一个函数对象,对象都可以有属性,b 处定义Foo的getName属性为函数,输出2; getName(),这里看d、e处,d为函数表达式,e为函数声明,两者区别在于变量提升,函数声明的 5 会被后边函数表达式的 4 覆盖; Foo().getName(),这里要看a处,在Foo内部将全局的getName重新赋值为 console.log(1) 的函数,执行Foo()返回 this,这个this指向window,Foo().getName() 即为window.getName(),输出 1; getName(),上面3中,全局的getName已经被重新赋值,所以这里依然输出 1; new Foo.getName(),这里等价于new (Foo.getName()),先执行 Foo.getName(),输出 2,然后new一个实例; new Foo().getName(),这里等价于 (new Foo()).getName(), 先new一个Foo的实例,再执行这个实例的getName方法,但是这个实例本身没有这个方法,所以去原型链__protot__上边找,实例.__protot__ === Foo.prototype,所以输出 3; new new Foo().getName(),这里等价于new (new Foo().getName()),如上述6,先输出 3,然后new 一个new Foo().getName() 的实例。

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()

输出结果:

a Uncaught TypeError: f.b is not a function a b

解析:

f 并不是 Function 的实例,因为它本来就不是构造函数,调用的是 Function 原型链上的相关属性和方法,只能访问到 Object 原型链。所以 f.a() 输出 a ,而 f.b() 就报错了。 F 是个构造函数,而 F 是构造函数 Function 的一个实例。因为 F instanceof Object === true,F instanceof Function === true,由此可以得出结论:F 是 Object 和 Function 两个的实例,即 F 能访问到 a, 也能访问到 b。所以 F.a() 输出 a ,F.b() 输出 b。

4. 代码输出结果

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

解析:

Foo.a() 这个是调用 Foo 函数的静态方法 a,虽然 Foo 中有优先级更高的属性方法 a,但 Foo 此时没有被调用,所以此时输出 Foo 的静态方法 a 的结果:4 let obj = new Foo(); 使用了 new 方法调用了函数,返回了函数实例对象,此时 Foo 函数内部的属性方法初始化,原型链建立。 obj.a() ; 调用 obj 实例上的方法 a,该实例上目前有两个 a 方法:一个是内部属性方法,另一个是原型上的方法。当这两者都存在时,首先查找 ownProperty ,如果没有才去原型链上找,所以调用实例上的 a 输出:2 Foo.a() ; 根据第2步可知 Foo 函数内部的属性方法已初始化,覆盖了同名的静态方法,所以输出:1

5. 代码输出结果

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。

6. 代码输出结果

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

解析:

console.log(b.n),在查找b.n是首先查找 b 对象自身有没有 n 属性,如果没有会去原型(prototype)上查找,当执行var b = new B()时,函数内部this.n=9999(此时this指向 b) 返回b对象,b对象有自身的n属性,所以返回 9999。 console.log(c.n),同理,当执行var c = new C()时,c对象没有自身的n属性,向上查找,找到原型 (prototype)上的 n 属性,因为 A.n++(此时对象A中的n为4400), 所以返回4400。

7. 代码输出问题

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

解析:

console.log(new A().a),new A()为构造函数创建的对象,本身没有a属性,所以向它的原型去找,发现原型的a属性的属性值为1,故该输出值为1; console.log(new B().a),ew B()为构造函数创建的对象,该构造函数有参数a,但该对象没有传参,故该输出值为undefined; console.log(new C(2).a),new C()为构造函数创建的对象,该构造函数有参数a,且传的实参为2,执行函数内部,发现if为真,执行this.a = 2,故属性a的值为2。

8 代码输出问题

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] 5 child1.show(); // 11 [1,2,1] 5 child2.show(); // 12 [1,2,1] 5 parent.show(); // 1 [1,2,1] 5 child1.show(); // 5 [1,2,1,11,12] 5 child2.show(); // 6 [1,2,1,11,12] 5

这道题目值得神帝,他涉及到的知识点很多,例如this的指向、原型、原型链、类的继承、数据类型等。

解析

parent.show(),可以直接获得所需的值,没啥好说的; child1.show(),Child的构造函数原本是指向Child的,题目显式将Child类的原型对象指向了Parent类的一个实例,需要注意Child.prototype指向的是Parent的实例parent,而不是指向Parent这个类。 child2.show(),这个也没啥好说的; parent.show(),parent是一个Parent类的实例,Child.prorotype指向的是Parent类的另一个实例,两者在堆内存中互不影响,所以上述操作不影响parent实例,所以输出结果不变; child1.show(),child1执行了change()方法后,发生了怎样的变化呢? this.b.push(this.a),由于this的动态指向特性,this.b会指向Child.prototype上的b数组,this.a会指向child1a属性,所以Child.prototype.b变成了[1,2,1,11]; this.a = this.b.length,这条语句中this.athis.b的指向与上一句一致,故结果为child1.a变为4; this.c.demo = this.a++,由于child1自身属性并没有c这个属性,所以此处的this.c会指向Child.prototype.cthis.a值为4,为原始类型,故赋值操作时会直接赋值,Child.prototype.c.demo的结果为4,而this.a随后自增为5(4 + 1 = 5)。 child2执行了change()方法, 而child2child1均是Child类的实例,所以他们的原型链指向同一个原型对象Child.prototype,也就是同一个parent实例,所以child2.change()中所有影响到原型对象的语句都会影响child1的最终输出结果。 this.b.push(this.a),由于this的动态指向特性,this.b会指向Child.prototype上的b数组,this.a会指向child2a属性,所以Child.prototype.b变成了[1,2,1,11,12]; this.a = this.b.length,这条语句中this.athis.b的指向与上一句一致,故结果为child2.a变为5; this.c.demo = this.a++,由于child2自身属性并没有c这个属性,所以此处的this.c会指向Child.prototype.c,故执行结果为Child.prototype.c.demo的值变为child2.a的值5,而child2.a最终自增为6(5 + 1 = 6)。

9. 代码输出结果

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());

输出结果:true

实际上,这段代码就是在实现原型链继承,SubType继承了SuperType,本质是重写了SubType的原型对象,代之以一个新类型的实例。SubType的原型被重写了,所以instance.constructor指向的是SuperType。具体如下:

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
海洋cms源码(海洋CMS模板免费下载官网手机版——构建您的海洋梦想起航)