[JS]原型的基本概念

目录
  • 原型系统
    • 原型
      • 基本概念
      • 示例
      • 关系
    • 改进创建对象的模式
      • 单纯使用原型模式创建对象
      • 综合构造函数和原型模式创建对象

原型系统

原型

基本概念

  • 原型(prototype)是函数特有的属性。

  • 只要创建了一个函数,这个函数就会自动创建一个prototype属性(显式原型),并指向该函数的原型对象。

  • 原型对象上都有一个constructor属性,指向prototype属性所在的函数(即函数本身)。

  • 而对于每一个构造函数创建出的实例对象,内部都会有一个[[Prototype]]属性(隐式原型),同样指向函数的原型对象。


    • 在Firefox、Safari和Chrome浏览器中,每个对象都可以通过__proto__属性访问到它们的[[Prototype]]属性。

    • 对其他浏览器而言,这个属性对脚本是不可见的(使用

      getPrototypeOf()
      方法获取类的原型)。

示例

 // 创建一个函数
function Person(){};

// 检查其是否有prototype这个属性
console.log(Person.hasOwnProperty('prototype'));
// 查看Person.prototype的内容
console.log(Person.prototype);

从输出结果可以看出,

Person
函数确实拥有
prototype
这个属性,并且
Person.prototype
这个原型对象包含了一个
constructor
属性,指向了一个函数,这个函数就是构造函数
Person()

 // 补充上面Person()构造函数的原型
Person.prototype.name = '张三';
Person.prototype.age = 20;
Person.prototype.sayName = function(){
console.log(this.name);
}

// 创建对象
const person = new Person();
// 输出对象
console.log(person);

从输出结果可以看出,由于将属性和方法都放到了

prototype
上,输出
person
这个实例对象的时候是找不到
name
age
sayName()
方法的,只有一个隐式原型对象
[[Prototype]]
,在这个隐式原型对象上才能找到
name
age
sayName()
方法,以及指向构造函数
Person()
constructor
属性。

使用原型的好处就是可以共享属性和方法。

 // 创建两个对象
const person1 = new Person();
const person2 = new Person();

console.log(person1 === person2); // false
console.log(person1.sayName === person2.sayName); // true
  • person1 === person2
    会返回
    false
    ,因为它们是两个不同的对象。

  • person1.sayName === person2.sayName
    会返回
    true
    ,因为这两个不同的对象共享这同一个
    sayName()
    方法。

关系

构造函数原型对象实例对象 三个的关系如下图:

改进创建对象的模式

单纯使用原型模式创建对象

这种模式将所有的属性和方法都进行共享。

 function Person(){};

// 将属性添加到原型上
Person.prototype.name = '张三';
Person.prototype.age = 20;
Person.prototype.sayName = function(){
console.log(this.name);
}


const person1 = new Person();
const person2 = new Person();

确实,方法共享后,节省了内存,但是缺点是属性也随之共享了。

例如上面这个例子,

person1
person2
这两个对象创建后的
name
age
都是
张三
20

可以再手动修改对象的属性:

 person2.name = '李四';
person2.age = 18;

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

不需要共享的属性 放在构造函数上,将 共享的属性和方法 放在原型对象上。

同时,可以使用默认值来改进构造函数。

 function Person(name='张三', age=20){
this.name = name;
this.age = age;
}

Person.prototype.sayName = function(){
console.log(this.name);
}

const person1 = new Person();
const person2 = new Person('李四',18);

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

  • Person()构造函数的参数列表:
    name='张三',age=20
    表示
    name
    的默认值是
    '张三'
    age
    的默认值是
    20

另一种设置默认值的方式是:

 function Person(name,age){
this.name = name || '张三';
this.age = age || 20;
}

如果

name
age
没有传入参数,则为
undefined
,在 运算符中会被转为
false
,最终赋值给
name
age
的是 运算符右边的数据。

  • 由于

    person1
    在创建的时候没有传入参数,所以默认是
    张三,20
    ;而
    person2
    在创建的时候传入了参数,所以属性是
    李四,18

  • 输出两个对象,发现它们只有

    name
    age
    两个 私有属性
    sayName()
    方法在原型对象上,是 共享 的。

标签: Javascript

添加新评论