javascript-prototype-原型

119 阅读2分钟

一、什么是原型

函数的原型对象
  在javascript中,我们创建(声明)一个函数a,那么浏览器就会在内存中创建一个对象b。这个对象b就是函数a的原型对象,这个原型对象b默认会有一个属性constructor指向这个函数a(意思就是说:constructor属性的值是函数a)
  声明的函数会有一个默认的属性叫prototype,而且浏览器会创建一个对象,这个对象就是函数的原型对象,prototype属性指向这个对象
  注意:原型对象默认只有属性constructor,其他都是从object继承而来,暂时不考虑

function person() {
}

console.log(person.prototype) //打印值是一个对象
image.png image.png

使用构造函数创建对象
  把一个函数作为一个构造函数(理论上任何函数都可以作为构造函数)使用new创建对象的时候,那么这个对象就会存在一个默认的不可见的属性,来指向构造函数的原型对象.这个不可见的属性一般用[[prototype]]来表示,只是这个属性没有办法直接访问到

function person() {

}
var p = new person();
console.log(person.prototype)
console.log(p)
image.png

使用new会创建一个对象,在这个对象有一个属性[[prototype]] ,[[prototype]]指向原型对象

image.png

image.png

<script>
    function person() {
    }
    //可以使用person.prototype直接访问到原型对象
    //给person函数的原型对象添加一个属性name,并且值是 张三
    person.prototype.name = "张三"
    person.prototype.age = "18"

    var p1 = new person();
    /*访问p1对象的属性name,虽然在p1对象中我们没有明确添加属性name,
      但是p1的[[prototype]]属性指向的原型中有name属性,所以这个地方就可以访问到属性name的值*/
    console.log(p1.name);   //张三

    var p2 = new person();
    console.log(p2.name); //张三  都是从原型中找到的,所以都一样
    console.log(p1.name === p2.name); //ture

    //由于不能修改原型中的值,则这种情况就直接在p1中添加了一个新属性name,然后在p1中无法再访问到原型中的属性  
    p1.name = "李四";
    console.log(p1.name);//李四
    console.log(p2.name);//张三
</script>
image.png

二、与原型相关的几个属性和方法

1. prototype属性
prototype存在于构造函数中(其实任意函数中都有,只是不是构造函数的时候prototype我们不关注),他指向这个构造函数的原型对象
2. constructor属性
constructor属性存在于原型对象中,他指向了构造函数

function person() {

};
console.log(person.prototype.constructor === person);//true

var p1 = new person();
//使用instanceof操作符可以判断一个对象的类型
//typeof一般用来获取简单类型和函数,
//引用类型一般使用instanceof,因为引用类型用type,总是返回object
console.log(p1 instanceof person) //true

我们根据需要,可以person.prototype属性指定新的对象,来作为person的原型对象
但是这个时候有个问题,新的对象的constructor属性则不再指向person构造函数了

<script>
  function person() {
  }

  person.prototype = {
    name: "四月",
    age: 20
  }
  var p1 = new person();
  console.log(p1.name);//四月
  console.log(p1 instanceof person)//true
  console.log(person.prototype.constructor === person)//false

  //如果constructor对你很重要,你应该在person.prototype中添加这样一行代码:
  person.prototype = {
    constructor: person //让constructor重新指向person函数
  }
</script>

3. hasOwnProperty()方法
  我们访问一个对象的属性的时候,这个属性有可能来自对象本身,也有可能来自这个对象的[[prototype]]属性指向的原型
  hasOwnProperty()方法,可以判断一个属性是否来自对象本身

  <script>
    function person() {
    }
    person.prototype.name = "四月"
    var p1 = new person();
    p1.sex = "男"

    //sex属性是直接在p1上添加的,所以是true
    console.log(p1.hasOwnProperty("sex"));
    //name是在原型上添加的,所以是false
    console.log(p1.hasOwnProperty("name"));
    //age属性不存在所以也是false
    console.log(p1.hasOwnProperty("age"));
  </script>

image.png

组合原型模型和构造函数模型创建对象

image.png

image.png image.png

image.png 构造函数方法内部封装属性,原型对象内封装方法

image.png