原型继承的优缺点(原型&继承题目及内容解答)
这里给大家分享我在网上总结出来的一些知识 ,希望对大家有所帮助
这道义题目考察原型 、原型链的基础 ,记住就可以了 。
2. 代码输出结果
输出结果: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. 代码输出结果
输出结果:
解析:
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. 代码输出结果
输出结果: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 函数内部的属性方法已初始化 ,覆盖了同名的静态方法 ,所以输出:15. 代码输出结果
输出结果:true
解析:
因为constructor是prototype上的属性 ,所以dog.constructor实际上就是指向Dog.prototype.constructor;constructor属性指向构造函数。instanceof而实际检测的是类型是否在实例的原型链上 。
constructor是prototype上的属性 ,这一点很容易被忽略掉 。constructor和instanceof 的作用是不同的 ,感性地来说,constructor的限制比较严格 ,它只能严格对比对象的构造函数是不是指定的值;而instanceof比较松散 ,只要检测的类型在原型链上,就会返回true。
6. 代码输出结果
输出结果: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. 代码输出问题
输出结果: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 代码输出问题
输出结果:
这道题目值得神帝,他涉及到的知识点很多 ,例如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会指向child1的a属性,所以Child.prototype.b变成了[1,2,1,11]; this.a = this.b.length ,这条语句中this.a和this.b的指向与上一句一致,故结果为child1.a变为4; this.c.demo = this.a++ ,由于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的最终输出结果 。 this.b.push(this.a) ,由于this的动态指向特性 ,this.b会指向Child.prototype上的b数组,this.a会指向child2的a属性,所以Child.prototype.b变成了[1,2,1,11,12]; this.a = this.b.length ,这条语句中this.a和this.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. 代码输出结果
输出结果:true
实际上 ,这段代码就是在实现原型链继承,SubType继承了SuperType ,本质是重写了SubType的原型对象 ,代之以一个新类型的实例 。SubType的原型被重写了 ,所以instance.constructor指向的是SuperType 。具体如下:
如果对您有所帮助 ,欢迎您点个关注 ,我会定时更新技术文档 ,大家一起讨论学习 ,一起进步 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!