JavaScript基础学习-原型

从对象说起

JavaScript是面向对象的语言,而JavaScript的实现方式和常见的(比如Java)不一样,JavaScript不通过类来抽象对象,直接创建创建对象,JavaScritpt中只有对象。

[[Prototype]]

几乎所有对象在创建的时 对象的[[Prototype]]都会被赋予一个非空的值
这个值可以通过a.__proto__获取,也可以通过Object.getPrototypeOf(a)来获取
var a = {}
在这里插入图片描述
在这里插入图片描述
对象的[[Prototype]]最终会指向Objects.prototype
在这里插入图片描述

原型的作用

JavaScript面向对象的方式不是通过类的复制(像Java一样),而是通过对象的关联,对象的关联就是通过原型
我们创建一个对象b并把它关联到对象a,发现b的原型指向a。
当我们访问b.a时,虽然b中不存在a,会通过原型一直向上查找(直到找到Object),在a的原型中找到a。

  var a = { a: 2 },
    b = Object.create(a);

  console.log(b);
  console.log(b.a); // 2
  console.log(Object.getPrototypeOf(b) === a); // true

对象b
在这里插入图片描述

关于函数
  • 函数也是对象也会有原型,函数还有一个prototype属性,当我们使用new 来调用这个函数时,生成的对象[[Prototype]]会关联函数的prototype
  • JavaScript中并不存在构造函数,只有当使用new 调用函数时,函数调用会变成 构造函数调用。
  • 通常我们会把通过new 调用的函数的函数名首字母大写,然而对于JavaScript引擎来说首字母大写没有任何意义。

当我们使用new 调用一个函数时,发生了下面的过程

  1. 创建一个新对象
  2. 这个对象会被执行[[Prototype]]连接
  3. 这个新对象会绑定到函数调用的this
  4. 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象(this)
  function Foo(name) {
    this.name = name;
  }

  Foo.prototype.myName = function() {
    return this.name;
  };

  var a = new Foo('a');

  console.log(a);
  console.log(a.myName()); // a
  console.log(a.constructor === Foo); // true
  console.log(Foo.constructor === Function);
  console.log(Foo.prototype.constructor === Foo); // true

对象a
a有一个自身的name属性,a的原型有一个来自Foo的myName()函数,和构造器constructor,a的constructor指向Foo,Foo.prototype.constructor也默认指向Foo。

在这里插入图片描述


a的 .constructor属性指向Foo,并不能说明a是由Foo“构造的”,它们之间只是委托关系
Foo.prototype的.constructor属性只是Foo函数在声明时的默认属性,可以修改
当修改了Foo.prototype后,a.constructor在“{}”中没有发现constructor属性,继续向原型链上层查找,找到Object,所以a.constructor===Object

  function Foo() {}
  Foo.prototype = {};
  var a = new Foo();
  console.log(a.constructor === Foo); // false
  console.log(a.constructor === Object); // true
继承
  • Bar.prototype = Object.create(Fun.prototype)。通过Object.create()的方式创建Bar.prototype 会创建一个新的对象并把新对象内部的[[prototype]]关联到Foo.prototype。这样做会使Bar.prototype.constructor属性丢失
  • 当使用Bar.prototype = Fun.prototype时 ,会使Bar.prototype和Fun.prototype共同引用同一个对象,当对Bar.prototype赋值时,同时也会使Fun.prototype变化,失去继承的意义。
  • ES6提供了更好的方法 Object.setPrototypeOf(Bar.prototype,Fun.prototype)
  function Fun(name) {
    this.name = name;
  }

  Fun.prototype.myName = function() {
    return this.name;
  };

  function Bar(name, lable) {
    Fun.call(this, name);
    this.lable = lable;
  }

  // Bar.prototype = Fun.prototype;
  // Bar.prototype = new Fun();
  Bar.prototype = Object.create(Fun.prototype);
  // Object.setPrototypeOf(Bar.prototype, Fun.prototype);
  Bar.prototype.myName = function() {
    return this.name + 'jsong';
  };

  var a = new Bar('jsong');
  console.log(a.myName()); // jsongjsong

  var b = new Fun('js');
  console.log(b.myName()); // js
发布了83 篇原创文章 · 获赞 21 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/JsongNeu/article/details/96361640
今日推荐