资讯专栏INFORMATION COLUMN

原型链知识记录

Noodles / 1044人阅读

摘要:此贴用于记录原型链相关的一些东西。在里,函数都有,对象都有,一个函数的和一个对象的就是原型,原型其实也是一个对象。如果原型链很长,当访问某个属性的时候,会话更多的时间,需要注意原型链不要太长。在引入的之前,函数的继承就是通过原型来实现的。

此贴用于记录原型链相关的一些东西。
在JavaScript里,函数都有prototype,对象都有__proto__,一个函数的prototype和一个对象的__proto__就是原型,原型其实也是一个对象。
一个函数的prototype和这个函数的示例对象的__proto__是同一个引用,即:

function A(){
}

let a = new A();
console.log(a.__proto__ === A.prototype); //返回的是true

当调用某一个对象的方法的时候,如果找不到这个对象的方法,则会去找这个对象的原型里的方法,如果再找不到,则继续找原型的原型的方法,一直往上找,这个就是原型链,如果都找不到,则会报错。

如果原型链很长,当访问某个属性的时候,会话更多的时间,需要注意原型链不要太长。

在引入es6的extends之前,函数的继承就是通过原型来实现的。下面记录一下我理解的继承,下面的继承参考的是[JS继承的实现方式
][1],他那里有完整的继承方法。

一. 原型链继承
function A(name) {
  this.name = name;
  this.f1 = function () {
    console.log(this.name + "正在做f1");
  }
}
A.prototype.f2 = function () {
  console.log(this.name + "正在做f2");
}

function B(name) {
  this.name = name;
}

B.prototype = new A("");

let b = new B("test");
b.f1();
b.f2();
console.log(b.__proto__ === B.prototype); //true

console.log(b instanceof A);//true
console.log(b instanceof B);//true

上述例子中,b居然是A的实例对象,也是B的实例对象,这样其实是有问题的,需要在B.prototype = new A("");后面加上:

B.prototype.constructor = B;

优点:
1.简单,实现容易
2.能访问父类所有的方法和属性

缺点:
1.要给B的prototype新增方法必须要在 new A("");之后
2.无法实现多继承
3.没法向父类的构造函数传递参数
4.实例是当前类的实例,也是父类的实例

二. 构造继承
function A(name){
  this.name = name;
  this.f1 = function(){
    console.log(this.name + "正在做f1");
  }
}
A.prototype.f2 = function(){
  console.log(this.name + "正在做f2");
}

function B(name) {
  A.call(this, name);
}

let b = new B("test");
b.f1();
// b.f2();// 会报错

console.log(b instanceof A);//false
console.log(b instanceof B);//true

优点:
1.可以使用父类的属性和方法
2.可以实现多重继承,即可以call多个函数
3.实例对象是当前类的实例,不是父类的实例
缺点:
1.无法获取A的prototype的属性和方法
2.只是子类的实例,不是父类的实例
3.无法实现函数复用,每个子类都有父类实例函数的副本,影响性能(此处应该是调用call的时候会生成父类的实例副本,具体的还得再研究研究)

三. 组合继承
function A(name){
  this.name = name;
  this.f1 = function(){
    console.log(this.name + "正在做f1");
  }
}
A.prototype.f2 = function(){
  console.log(this.name + "正在做f2");
}

function B(name) {
  A.call(this, name);
}
B.prototype = new A("");
//要修正prototype的constructor,为什么要修正还有待研究
B.prototype.constructor = B;

let b = new B("test");
b.f1();
b.f2();

console.log(b instanceof A);//true
console.log(b instanceof B);//true

优点:
1.包含了原型链继承和构造继承的优点
2.解决了原型链继承的无法实现多继承和没法向父类的构造函数传递参数的缺点
3.解决了构造继承无法获取A的prototype的属性和方法还有只是子类的实例,不是父类的实例的问题
缺点:
1.调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

四.寄生组合继承
function A(name){
  this.name = name;
  this.f1 = function(){
    console.log(this.name + "正在做f1");
  }
}
A.prototype.f2 = function(){
  console.log(this.name + "正在做f2");
}

function B(name) {
  A.call(this, name);
}

(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = A.prototype;
  //将实例作为子类的原型,这样就可以只获取A的prototype的属性了
  B.prototype = new Super();
  //
  B.prototype.constructor = B;
})();

let b = new B("test");
b.f1();
b.f2();

console.log(b instanceof A);//true
console.log(b instanceof B);//true

优点:
1.在组合继承的基础上,只生成了一份父类的实例,prototype也只继承了父类的prototype,没有继承私有的属性
缺点:
1.实现复杂

顺便加一个知识点,当使用new关键字来创建对象的时候,也用到了原型相关的知识,所以也记在了这里;
假设有一个function A(name){ this.name = name; };使用new关键字创建一个A的实例对象let a = new A();
new关键字主要做了以下几个步骤:
(1)创建一个空的对象
var obj = {};
(2)将这个对象的原型__proto__指向A的prototype
obj.__proto__ = A.prototype
(3)函数A的this指向obj;接着执行A函数
(4)将obj返回,变量a指向obj

本文主要是参考了别人的文章,写一些自己的理解,如果有什么写错的地方欢迎大神来指正一下

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101767.html

相关文章

  • 「JS篇」你不知道的 JS 知识点总结(一)

    摘要:调用栈就是为了到达当前执行位置所调用到的所用函数。方法测试是否至少有一个元素通过由提供的函数实现的测试返回值是终止。然而,如果存在于原型链上层,赋值语句的行为就会有些不同而且可能很出人意料。 typeof null 为 object 解释 不同的对象在底层都表示为二进制,在JavaScript中二进制前三位都为0的话会被判断为object类型,null 的二进制表示都是0,自然前三位都...

    JouyPub 评论0 收藏0
  • 记录一次杭州顺网科技的面试过程

    摘要:以上是面试中笔试涉及到的知识点或者后面被问到的只是点。也许是根据薪资和面试的等级来出题的。我刚面试完回家,吃了一个泡面,回忆下面试题。同时作为传递到构造函数,执行了一次让构造函数里面的属性和方法赋值了一份给。 css 如何水平垂直居中,请尽量多说几种方法?很尴尬,我多次面试都被问到这个问题,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...

    shiguibiao 评论0 收藏0
  • 记录一次杭州顺网科技的面试过程

    摘要:以上是面试中笔试涉及到的知识点或者后面被问到的只是点。也许是根据薪资和面试的等级来出题的。我刚面试完回家,吃了一个泡面,回忆下面试题。同时作为传递到构造函数,执行了一次让构造函数里面的属性和方法赋值了一份给。 css 如何水平垂直居中,请尽量多说几种方法?很尴尬,我多次面试都被问到这个问题,fuck 定位(回答了)、table-cell布局、flex布局、translate+relat...

    caiyongji 评论0 收藏0
  • JS笔记

    摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。异步编程入门的全称是前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。 TypeScript 入门教程 从 JavaScript 程序员的角度总结思考,循序渐进的理解 TypeScript。 网络基础知识之 HTTP 协议 详细介绍 HTT...

    rottengeek 评论0 收藏0
  • JS基础之常用小技巧和知识总结(二)

    摘要:组合使用构造函数模式和原型。构造函数用于定义实例属性,原型链用于定定方法和共享的属性。为了避免矛盾和意外的结果总是指定基数参数。 本文主要记录平时开发遇到的知识点和小技巧 原型对象与原型链 JavaScritp 引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回 undefined.原型链一般实现为一个链表...

    yacheng 评论0 收藏0

发表评论

0条评论

Noodles

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<