文档章节

JS原型和原型链

x
 xszl
发布于 2017/08/23 21:18
字数 1391
阅读 5
收藏 0

##创建对象 使用Object构造函数或者对象字面量可以创建单个对象,但面对创建多个对象的时候,代码无法复用,这显然不是我们所期望的,为了解决此问题,人们发明了以下几种创建对象的方式 ####工厂模式

  function createPerson(name, age) {
    var o = {};
    o.name = name;
    o.age = age;
    o.sayName = function() {
      console.log(this.name);
    }
    return o;
  }
  var person1 = createPerson('Tom', 27);
  person1.sayName();
  var person2 = createPerson('Jack', 28);
  person2.sayName();

使用工厂模式创建对象存在一个问题,就是无法识别对象。这才有了后面的构造函数模式 ####构造函数模式

  function Person(name, age) {
    this.name = name;
    this.age = age;
    this.sayName = function() {
      console.log(this.name);
    }
  }
  var person1 = new Person('Tom', 27);
  person1.sayName();
  var person2 = new Person('Jack', 28);
  person2.sayName();

  console.log(person1.constructor == Person);
  console.log(person1 instanceof Person);

  console.log(person1.sayName == person2.sayName);

创建Person实例会经历4个步骤

  1. 创建一个新对象
  2. 将构造函数(Person)的作用域赋值给新对象
  3. 执行构造函数代码
  4. 返回新对象

使用这种方式能通过constructor 或者instanceof 来识别对象类型,但还存在一个问题,就是构造函数中的方法sayName()会在每次创建新实例时构建一次,也就是方法没办法复用。使用原型模式可以解决这个问题 ####原型模式 每个函数创建时都有一个prototype属性,指向一个原型对象,这个原型对象包含所有实例共享的属性和方法。

  function Person() {

  }
  Person.prototype.name = 'Tom';
  Person.prototype.age = 27;
  Person.prototype.sayName = function() {
    console.log(this.name);
  }
  person1 = new Person();
  person1.sayName();
  person2 = new Person();
  
  console.log(person1.sayName == person2.sayName);

还可以以自变量定义的形式定义Person.prototype,写法更为简洁

  function Person() {

  }
  Person.prototype = {
    name: 'Tom',
    age: 27,
    sayName: function() {
      console.log(this.name);
    }
  };
  person1 = new Person();
  person1.sayName();
  person2 = new Person();

  console.log(person1.sayName == person2.sayName);

原型搜索机制:访问Person1的属性,首先从实例本身开始搜索,如果实例有该属性,则返回,如果没有,则继续搜索指针指向的原型对象,如果在原型对象中找到,返回属性值

原型模式也存在一定问题。默认情况下,所有实例的属性都是相同的,但这只是带来一些不便,最大的问题是属性的共享导致的,如果属性是引用类型,那么操作person1的属性会影响到person2的属性。 ####组合使用构造函数模式和原型模式 构造函数模式适合定义私有的属性,而原型模式适合定义共有的属性和方法。组合使用能发挥各自的长处,这种模式也是应用最为广泛的

  function Person(name, age) {
    this.name = name;
    this.age = age;
  }
  Person.prototype.sayName = function() {
    console.log(this.name);
  }
  person1 = new Person('Tom', 27);
  person1.sayName();
  person2 = new Person('Jack', 28);
  person2.sayName();
  console.log(person1.sayName == person2.sayName);

##继承 javascript中实现继承主要就是通过原形链来实现的。什么是原型链呢? ####原型链 了解原型链之前,我们先来回顾下构造函数、原型和实例之间的关系:每个构造函数在创建之初会有一个prototype(原型)属性,这个原型属性是一个指向构造函数的原型对象的指针,原型对象包含一个指向构造函数的指针constructor。然后调用构造函数创建一个实例,这个实例的内部又会包含一个指针(__proto__),这个指针指向构造函数的原型对象。上述中创建person1实例,在控制台可以看到如下信息。 输入图片说明

假设有两个构造函数A()和B(),让B的原型对象等于A的实例,那么B的原型对象会包含一个指针(__proto__)指向A的原型对象,如果再有一个构造函数C(),让C的原型对象等于B的实例,如此层层递进,就构成了原型和实例之间的链条,也就是所谓的原型链

  function Super() {
    this.superproperty = true;
  }
  Super.prototype.getSuperValue = function() {
    console.log(this.superproperty);
  }
  function Sub() {
    this.subproperty = false;
  }
  // 继承Super
  Sub.prototype = new Super();
  Sub.prototype.getSubValue = function() {
    console.log(this.subproperty);
  }
  var instance = new Sub();
  instance.getSuperValue();

结合上文提到的原型搜索机制,访问instance.getSuperValue(),先搜索实例Sub,然后实例没有会去搜索Sub.prototype,仍然没有找到,会再去Super.prototype中查找,这才找到getSuperValue方法。在找不到属性或者方法的情况下,搜索过程会沿着原型链一环一环前进,直到末端才会停下。 ####原型链的问题 原型链很强大,可以实现javascript的继承,但它存在一些问题,就如同上文中使用原型模式创建对象遇到的问题一样。

  1. 省略了为构造函数传递参数这一环节,导致所有Sub实例初始的属性都一样
  2. 如果属性是引用类型,那么所有的Sub实例会共享属性 ####借用构造函数
  function Super(name) {
    this.name = name;
  }

  function Sub() {
    // 继承Sup并且传递参数
    Super.call(this, 'Tom');
    // 实例属性
    this.age = 27;
  }
  var instance = new Sub();
  console.log(instance.name, instance.age);

在sub的构造函数中调用sup的构造函数,这样每个sub的实例就会拥有sup的属性。但是借用构造函数有一个问题,在使用构造函数创建对象也遇到过:不论是在sub中定义的函数还是sup中定义的函数无法复用。 ###组合继承 将原型链和借用构造函数结合使用,发挥各自的长处,成为javascript中最常见的继承模式

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

  function Sub(name, age) {
    // 继承Sup属性
    Super.call(this, name);

    this.age = age;
  }
  Sub.prototype = new Super();
  Sub.prototype.sayName = function() {
    console.log(this.age);
  }
  var instance = new Sub('Tom', 27);
  instance.sayName();

© 著作权归作者所有

x
粉丝 0
博文 14
码字总数 17267
作品 0
私信 提问
简单理解JavaScript原型链

简单三连 什么是原型 ? 我是这样理解的:每一个JavaScript对象在创建的时候就会与之关联另外一个特殊的对象,这个对象就是我们常说的原型对象,每一个对象都会从原型“继承”属性和方法。 什么...

森林小猎人
05/07
0
0
关于javascript的原型和原型链系列

关于javascript的原型和原型链,看我就够了(一) https://mp.weixin.qq.com/s/rxhAu9JW3Ji4uGhz3XW8Q 关于javascript的原型和原型链,看我就够了(二) https://mp.weixin.qq.com/s/uSPaW0y...

大灰狼的小绵羊哥哥
2018/11/10
0
0
如何理解JavaScript的原型和原型链?

之前有朋友在公众号给我留言,问问怎么去理解原型和原型链的问题。这个问题,在面试中,很多同学经常都会遇到。 回复多了,觉得大家对这块知识点理解还是不够深。于是决定今天来给大家讲讲,...

WEB开发阿靖
2018/12/07
0
0
理解 JavaScript 中的原型

前言 JavaScript 中的原型一直是我很惧怕的一个主题,理由很简单,因为真的不好理解,但它确实是 JavaScript 中很重要的一部分,而且是面试的必考题,就算现在不懂,以后迟早有一天要把它弄懂...

4Ark
01/22
0
0
关于javascript的原型和原型链,看我就够了(一)

关于js的原型和原型链,有人觉得这是很头疼的一块知识点,其实不然,它很基础,不信,往下看 要了解原型和原型链,我们得先从对象说起 创建对象 创建对象的三种方式: 对象直接量 通过对象直...

陌上寒
2018/11/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

威胁快报|新兴挖矿团伙借助shodan作恶,非web应用安全再鸣警钟

近日,阿里云安全发现了一个使用未授权访问漏洞部署恶意Docker镜像进行挖矿的僵尸网络团伙。我们给这一团伙取名为Xulu,因为该团伙使用这个字符串作为挖矿时的用户名。 Xulu并不是第一个攻击...

阿里云官方博客
16分钟前
3
0
MD5 加密需要注意编码格式!!!

相信做过MD5加密的童鞋都遇到过字符编码的坑,一般加密出来的结果和其他人不一样都是字符编码不一致导致的,比如类文件的字符编码、浏览器的字符编码等和对方不一致,所以就需要转码统一字符...

jason_kiss
18分钟前
1
0
python中字符串的操作

https://www.jianshu.com/p/7fc851b6a7ee

writeademo
27分钟前
1
0
如何制定 Java 性能调优标准?

想让你的程序更快更稳,但是系统经常出各种 bug,无从下手?Java 性能调优全攻略来啦! 我有一个朋友,有一次他跟我说,他们公司的系统从来没有经过性能调优,功能测试完成后就上线了,线上也...

Java领航员
27分钟前
2
0
java博客项目

项目地址:https://github.com/otale/tale 项目演示地址:https://tale.biezhi.me/ 项目介绍:Tale使用轻量级mvc框架Blade进行开发,默认主题使用漂亮的pinghsu, 特征 设计简洁,界面美观 ...

编程资源库
28分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部