JavaScript之原型模式

JavaScript中有这样的一个概念,对象。

有不少人觉得Java这么语言才是面向对象的语言,JavaScript哪里面向对象了。

其实说JavaScript面向对象还不如说JavaScript基于对象。

例如:我们在对DOM进行操作的时候用到的一下方法 

var app = document.getElementById("app")
   app.style="width:100px"
   app.innerHTML="123"

 

我们获取了一个id为app的节点的时候,其实它就是一个对象。

然后我们通过".属性"来获取属性值或者给它赋值等等。

我们在看看一个例子!

 

var num = 123;
console.log(num.toString()); // “123”

 

 在这里我们定义了一个变量名为num,并且给它赋值为 数据类型为:Number ,值为123。

 然后我们通过num.toString() 方法 得出了字符串“123”,不是一般只有对象后面才能接 点属性名吗? obj.***

其实在JavaScript里万物皆可为对象。在这里我就不在一一细说了。

现在我们来研究一下什么是原型模式。

在JavaScript高级程序设计这本书里说道:

创建的每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法
如果按照字面意思来理解,那么 prototype 就是通过调用构造函数而创建的那个对象实例的原型对象。(我们来看看代码)
  function Person() {
  }

在JavaScript里第一个字母大写的函数称之为构造函数。我们来看看这个函数里有什么?

 

 

 你会发现,这里真的有一个书上说的prototype(原型)属性。

理解原型对象
  无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。
  在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。
  创建了自定义的构造函数之后,其原型对象默认只会取得 constructor 属性;至于其他方法,则都是从 Object 继承而来的。
  当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。

我们通过构造函数Person来创建一个实例出来来看看这个实例对象上有没有什么东西。

  function Person() {
  }
  Person.prototype.name="张三";
  var p1=new Person();
 console.log(p1.__proto__ === Person.prototype);  //true

 

 

 

你会发现通过构造函数创建出来的实例对象p1的(__proto__)属性 全等于 构造函数的prototype属性。

Firefox、Safari 和 Chrome 在每个对象上都支持一个属性__proto__

我们再通过Person构造函数来创建一个实例对象,来比较这两个对象。

function Person(age,sex) {
    this.age=age;
    this.sex=sex;
  }
  Person.prototype.name = "张三"
  var p1 = new Person(18,"男")
  var p2 = new Person(19,"女")
  console.log(p2 == p1) //false
  console.log(p1.__proto__ === p2.__proto__)  //true
  console.log(p1.name)  //张三
  console.log(p2.name) //张三
  console.log(p1.age)   //18
  console.log(p2.age)   //19
  console.log(p1.sex) //男
  console.log(p2.sex) //女
  p1.name="李四"

 console.log(p1.name) //李四 这是来自实例对象的属性name

console.log(p2.name) //张三 这是来自原型对象的属性name

在这里我们发现,实例对象p1与实例对象p2 的__proto__属性相等,这两个实例对象不相等,开始它们的name属性值相等。

而且构造函数里没有设置name属性,那么我们也可以通过p1.name,p2.name访问到,然后我们更改了p1.name的值。发现p1实例对象会追加一个name属性(JavaScript对象的动态性),然后再去访问p1,p2的name属性发现值不一样了。

每当代码读取某个对象的某个属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先
从对象实例本身开始。如果在实例中找到了具有给定名字的属性,则返回该属性的值;如果没有找到,
则继续搜索指针指向的原型对象,在原型对象中查找具有给定名字的属性。如果在原型对象中找到了这
个属性,则返回该属性的值。

原来通过同一个构造函数创建出来的实例对象,他们的原型对象都 指向 构造函数的原型属性。

看看它们的关系图

 

posted @ 2020-04-02 20:29  阿政想暴富  阅读(182)  评论(0编辑  收藏  举报