前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >详解JavaScript的继承和原型链(prototype)

详解JavaScript的继承和原型链(prototype)

原创
作者头像
Learn-anything.cn
发布2021-12-22 13:34:59
4770
发布2021-12-22 13:34:59
举报
一、原型链 是什么?

JavaScript 的每个实例对象都有一个指向上一层对象的私有属性(称之为 __proto__) ,上一层对象又指向再上一层对象,就这样层层向上直至 __proto__ 属性为 null ,最后这个对象就是 Object

这种通过 __proto__ 属性来链接对象的方法,称之为 原型链

var o = {a: 1};
// 原型链如下:
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
  return 2;
}
// 原型链如下:
// f ---> Function.prototype ---> Object.prototype ---> null

function f() {
  this.a = 1;
  this.b = 2;
}
let o = new f();
f.prototype.b = 3;
f.prototype.c = 4;
// 原型链如下:
// {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null
二、怎么使用?
1、Object.getPrototypeOf() 和 Object.setPrototypeOf()

ECMAScript 6 开始,可以通过 Object.getPrototypeOf() 和 Object.setPrototypeOf() 访问器来访问 __proto__ 属性。

function f() {
  this.a = 1;
  this.b = 2;
}

let o = new f();
// 1、为 f 的上层对象新增属性(推荐此种方式新增属性)
f.prototype.b = 3;
f.prototype.c = 4;

// 2、查看上层对象属性
console.log(Object.getPrototypeOf(o));

// 3、此种方式设置上层对象的属性,会覆盖掉所有旧属性,慎用
console.log(Object.setPrototypeOf(o, {e:5}));

// 4、查看新的上层对象属性
console.log(Object.getPrototypeOf(o));
2、prototype 与 Object.getPrototypeOf

两者功能一致,都是用来访问原型属性,区别是:

  • prototype 用于类,而 Object.getPrototypeOf() 用于实例;
  • 共享:所有实例都可以访问,新增的 prototype 属性。
function A(){
  this.a = "a";
}

let aIns = new A();

// 1、一个用于类型、一个用于实例
console.log(A.prototype);
console.log(Object.getPrototypeOf(aIns));

let bIns = new A();
// 2、共享:所有实例都可以访问 新增的原型属性
A.prototype.b = "b";
console.log(Object.getPrototypeOf(aIns).b);
console.log(Object.getPrototypeOf(bIns).b);
var o = new Foo();

// 上面代码是让 JavaScript 执行了下面代码

var o = new Object();
o.__proto__ = Foo.prototype;
Foo.call(o);
3、hasOwnProperty

当访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻原型链上的所有对象,最后判断属性是否存在。hasOwnProperty 是 JavaScript 中唯一一个不会遍历原型链的方法。

const object1 = {};
object1.property1 = 42;

console.log(object1.hasOwnProperty('property1'));
// expected output: true

console.log(object1.hasOwnProperty('toString'));
// expected output: false
4、undefined

没有赋值的属性是 undefined,所以无法通过 undefined 来判断属性是否存在。

三、继承

继承也是基于原型链的特性。ECMAScript6 引入 class 关键字来实现 类对象,但类对象也是基于原型链。

1、Object.create

用 Object.create 来创建继承对象。

var a = {a: 1};
// a ---> Object.prototype ---> null

var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (继承而来)

var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, 因为d没有继承Object.prototype
四、其他
1、性能

试图访问不存在的属性时会遍历整个原型链,在原型链上查找属性比较耗时,对性能有副作用。

2、错误实践

扩展内置原型会破坏封装,这不是好的解决方案,使用扩展内置原型的唯一理由是支持 JavaScript 引擎的新特性,如 Array.forEach

原生原型不应该被扩展,除非它是为了与新的 JavaScript 特性兼容。

五、参考文档

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、原型链 是什么?
  • 二、怎么使用?
    • 1、Object.getPrototypeOf() 和 Object.setPrototypeOf()
      • 2、prototype 与 Object.getPrototypeOf
        • 3、hasOwnProperty
          • 4、undefined
          • 三、继承
            • 1、Object.create
            • 四、其他
              • 1、性能
                • 2、错误实践
                • 五、参考文档
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档