全部学科
Python全栈
python
NodeJS全栈
nodejs
📝 1 篇文章 20 道配套习题

JS 原型链与继承

专题说明

本专题系统讲解JavaScript原型链与继承的进阶知识,涵盖原型链查找机制、原型链终点、构造函数与原型关系、原型链继承缺陷、原型式继承、ES6类语法、extends继承特性、instanceof原理等内容,深入理解JavaScript面向对象编程的核心机制。

学习目标

  1. 理解原型链查找机制与属性遮蔽
  2. 掌握原型链终点为null而非Object.prototype
  3. 理解构造函数prototype与实例__proto__的关系
  4. 掌握构造函数返回对象时对new操作的影响
  5. 理解原型链继承的引用类型共享问题
  6. 掌握原型链继承无法传参和原型覆盖问题
  7. 理解Object.create实现原型式继承
  8. 掌握ES6类的特性:必须new调用、严格模式、方法不可枚举
  9. 理解extends继承中super的作用与静态方法继承
  10. 掌握instanceof的原型链检查原理

学习内容

本专题涵盖以下核心知识点:

  • 原型链基础:属性查找机制、原型链终点、Object.create(null)
  • 构造函数与原型:prototype属性、constructor指向、new操作返回值
  • 原型链继承:引用类型共享问题、无法传参、原型覆盖问题
  • 原型式继承:Object.create用法、引用类型共享、简易实现原理
  • ES6类与继承:class特性、extends继承、super用法、静态方法继承
  • instanceof原理:原型链检查机制、边界情况、手动实现

学习建议

  1. 原型链终点是null,不是Object.prototype
  2. 理解原型链查找:自身属性优先,沿__proto__向上查找
  3. 构造函数返回对象时,new返回该对象而非新实例
  4. 原型链继承存在引用类型共享问题,需用构造函数继承解决
  5. Object.create(null)创建无原型对象,适合做字典
  6. ES6类必须用new调用,默认严格模式,方法不可枚举
  7. 子类constructor必须先调用super()才能使用this
  8. instanceof检查左侧原型链是否包含右侧prototype

📝 配套习题(20 题)

💡 参考答案在文末
判断题
1

原型链继承可以在创建子类实例时向父类构造函数传递参数。

A

B

2

如果ES6子类没有显式定义constructor,会自动添加一个默认constructor并调用super()。

A

B

3

在JavaScript中,所有原型链的终点都是 Object.prototype

A

B

4

当访问一个对象的属性时,JavaScript会沿着原型链向上查找,直到找到该属性或到达原型链末端。

A

B

5

ES6的class默认运行在严格模式下。

A

B

6

使用原型链继承时,子类的原型对象会被父类实例覆盖,导致子类原有的原型方法丢失。

A

B

单选题
7

以下代码的输出结果是什么?

JavaScript
function Person(name) {
    this.name = name;
    return { age: 18 };
}

const p = new Person('Tom');
console.log(p.name);
console.log(p.age);
A

'Tom', undefined

B

'Tom', 18

C

undefined, 18

D

报错

8

以下代码的输出结果是什么?

JavaScript
const obj = Object.create(null);
console.log(obj.__proto__);
console.log(obj.toString);
A

undefined, undefined

B

null, undefined

C

undefined, 报错

D

null, null

9

以下代码的输出结果是什么?

JavaScript
function Foo() {}
const f1 = new Foo();

Foo.prototype = { name: 'bar' };

const f2 = new Foo();
console.log(f1.name);
console.log(f2.name);
A

undefined, 'bar'

B

'bar', 'bar'

C

undefined, undefined

D

报错

10

以下代码的输出结果是什么?

JavaScript
function Parent() {}
Parent.prototype.name = 'parent';

const child = new Parent();
child.name = 'child';

console.log(child.name);
delete child.name;
console.log(child.name);
A

'child' 然后是 'parent'

B

'child' 然后是 undefined

C

'parent' 然后是 'parent'

D

'parent' 然后是 undefined

11

以下代码的输出结果是什么?

JavaScript
const person = {
    name: 'parent',
    friends: ['Alice', 'Bob']
};

const child = Object.create(person);
child.name = 'child';
child.friends.push('Charlie');

console.log(person.name);
console.log(person.friends);
A

'parent', ['Alice', 'Bob']

B

'parent', ['Alice', 'Bob', 'Charlie']

C

'child', ['Alice', 'Bob', 'Charlie']

D

'child', ['Alice', 'Bob']

12

以下代码的输出结果是什么?

JavaScript
const proto = { x: 1, y: 2 };
const obj = Object.create(proto, {
    z: {
        value: 3,
        writable: true
    }
});

console.log(obj.x);
console.log(obj.y);
console.log(obj.z);
console.log(obj.hasOwnProperty('x'));
console.log(obj.hasOwnProperty('z'));
A

1, 2, 3, false, true

B

undefined, undefined, 3, false, true

C

1, 2, 3, true, true

D

1, 2, 3, true, false

13

以下代码的输出结果是什么?

JavaScript
const obj = Object.create(null);
console.log(obj instanceof Object);

function Foo() {}
Foo.prototype = null;
const f = new Foo();
console.log(f instanceof Foo);
A

false, false

B

false, true

C

true, false

D

报错

14

以下代码的输出结果是什么?

JavaScript
function Foo() {}
const f = new Foo();

console.log(f instanceof Foo);
console.log(f instanceof Object);
console.log(Foo instanceof Function);
console.log(Foo instanceof Object);
A

true, true, true, true

B

true, true, true, false

C

true, false, true, true

D

true, true, false, true

15

以下代码的输出结果是什么?

JavaScript
function Parent() {
    this.colors = ['red', 'blue'];
}

function Child() {}
Child.prototype = new Parent();

const c1 = new Child();
c1.colors.push('green');

const c2 = new Child();
console.log(c2.colors);
A

['red', 'blue']

B

['red', 'blue', 'green']

C

undefined

D

报错

多选题
16

关于构造函数和原型的关系,以下说法正确的有哪些?

A

每个构造函数都有一个 prototype 属性,指向一个原型对象

B

构造函数的 prototype 属性默认包含一个 constructor 属性,指向构造函数本身

C

通过 new 创建的实例,其 proto 指向构造函数的 prototype

D

构造函数本身也是一个对象,所以它也有 proto 属性

E

修改构造函数的 prototype 会影响已创建实例的原型链指向

17

关于ES6的extends继承,以下说法正确的有哪些?

A

子类必须在 constructor 中调用 super() 才能使用 this

B

extends 可以继承任何有 prototype 属性的对象(包括函数)

C

super 关键字既可以作为函数调用,也可以作为对象使用

D

子类继承父类时,会继承父类的静态方法

E

Object 可以被继承,因为 Object 也是构造函数

18

关于ES6的class,以下说法正确的有哪些?

A

class 本质上是构造函数的语法糖,prototype 属性依然存在

B

class 内部定义的方法默认不可枚举

C

class 必须使用 new 调用,不能作为普通函数直接调用

D

class 内部可以使用 var、let、const 定义变量

E

class 的静态方法需要使用 static 关键字声明

填空题
19

请填写Object.create的简易实现:

JavaScript
function myCreate(proto) {
    if (proto === null || typeof proto !== 'object') {
        throw new TypeError('Object prototype may only be an Object or null');
    }

    function F() {}
    F.prototype = !!1_proto!!;
    return !!2_new F()!!;
}
20

请填写instanceof的简易实现:

JavaScript
function myInstanceof(obj, constructor) {
    // 右侧必须是函数
    if (typeof constructor !== !!1_function!!) {
        throw new TypeError('Right-hand side is not callable');
    }

    // 获取对象的原型
    let proto = !!2_Object.getPrototypeOf(obj)!!;

    // 沿原型链查找
    while (proto !== !!3_null!!) {
        if (proto === constructor.prototype) {
            return true;
        }
        proto = Object.getPrototypeOf(proto);
    }
    return false;
}
参考答案
1.错误 2.正确 3.错误 4.正确 5.正确 6.正确 7.C 8.B 9.A 10.A 11.B 12.A 13.A 14.A 15.B 16.A;B;C;D;E 17.A;B;C;D;E 18.A;B;C;E 19.proto;new F() 20.function;Object.getPrototypeOf(obj);null
想在手机上练习这套专题?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一个专题 JS 函数与作用域
下一个专题 → JS 基础语法与变量
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码