构造函数

  • 主要用来初始化对象,即为对象成员变量赋初始值,总与new一起使用
  • 构造函数存在内存浪费的情况 ```javascript function Person(name, age) { this.name = name; this.age = age;

    this.sayName = function() {

    1. alert(this.name);

    } }

const person1 = new Person(‘小明’, 12); const person1 = new Person(‘小红’, 12);

  1. <a name="u72uK"></a>
  2. ### 问题
  3. 创建了对象,未使用new关键字实例化
  4. ```javascript
  5. function Person(name, age) {
  6. this.name = name;
  7. this.age = age;
  8. }
  9. const person1 = Person('小明', 12);
  10. console.log(person1) // undefined
  11. console.log(window.name) // 小明
  12. console.log(window.age) // 12
  13. // 使用安全模式创建对象
  14. function Person(name, age) {
  15. // 判断执行过程中this是否是当前这个对象
  16. // 如果是说明是通过new创建的
  17. if (this instanceof Person) {
  18. this.name = name;
  19. this.age = age;
  20. // 否则重新创建这个对象
  21. } else {
  22. return new Person(name, age);
  23. }
  24. }

new的作用

  • 在内存中创建一个新的对象;
  • 将构造函数的作用域赋给这个新对象(让this指向这个对象);
  • 执行构造函数里的代码,给这个新的对象添加属性和方法;
  • 返回这个新的对象。

    缺点

  • 每个方法都要在每个实例上重新创建一遍

原型prototype(显示原型)

  • 作用:共享属性和方法
  • 一般情况下,属性定义到构造函数里,方法定义到原型对象上
  • 每个函数都有一个prototype属性,它默认指向一个Object空对象(原型对象)
  • 原型对象中有一个属性constractor,它指向函数对象

    对象原型proto(隐式原型)

  • 指向构造函数的原型对象

  • 之所以对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有proto原型的存在
  • proto意义在于为对象的查找机制提供一个方向,它属于一个非标准属性,在实际开发中不可以使用这个属性,它只是内部用来指向原型对象prototype

    方法

  • hasOwnProperty:判断属性是否存在构造函数中 ```javascript function Person() {} Person.prototype.name = ‘小明’; Person.prototype.age = 12;

const person1 = new Person();

console.log(person1.hasOwnProperty(‘name’)) // —> false,存在原型中 person1.name = ‘小红’; console.log(person1.hasOwnProperty(‘name’)) // —> true,存在实例中

  1. - hasOwnPropertyin操作符:判断属性是否存在原型中
  2. ```javascript
  3. function hasPrototypeProperty(obj, name) {
  4. return !obj.hasOwnProperty(name) && (name in object);
  5. }

构造函数、实例、原型对象的关系

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。 —《JavaScript高级程序设计》(第三版)

  1. // 1、定义构造函数
  2. function Fn() {};
  3. // 2、创建实例对象
  4. const fn = new Fn();
  5. // fn.__proto__ === Fn.prototype
  6. // 3、给构造函数原型添加方法
  7. Fn.prototype.test = function() {};
  8. // 4、通过实例调用原型方法
  9. fn.test();

WeChat2684d251ea2cf869a609e502b79a21c3.png
构造函数和原型 - 图2

原型链

  • 作用:查找对象的方法(属性)
    • 先在自身属性上查找
    • 如果没有,则沿着proto向上查找,直到找到为止
    • 如果最后也没找到,返回undefined
  • 缺点:
    • 包含引用类型值的原型属性会被所有实例共享

WeChatbfaee7a7ee9dcb152f69b354eb1b3eda.png
image.png

this&prototype

  • 通过this添加属性、方法和通过prototype添加属性、方法的区别:

    通过this添加的属性、方法是在当前对象上添加的,然而js是一种基于原型prototype的语言,所以每创建一个对象时(当然在js中函数也是一种对象),它都有一个原型prototype用于指向其继承的属性。方法。这样通过prototype继承的方法并不是对象自身的,所以在使用这些方法时,需要通过prototype一级一级查找得到。这样通过this定义的属性或方法是该对象自身拥有的,所以每次通过类创建一个新对象时,this指向的属性和方法都会得到相应的创建。而通过prototype继承的属性或方法是每个对象通过prototype访问到,所以每次通过类创建一个新对象时这些属性和方法不会再次创建。