1. function Person(name, age, job) {
  2. this.name = name;
  3. this.age = age;
  4. this.job = job;
  5. this.sayName = function () {
  6. console.log(this.name);
  7. }
  8. };
  9. let p = new Person('Ethan', 24, 'java')
  10. console.log(p.name); // Ethan

构造函数实际上会经历以下 4 个步骤:

  1. 在内存创建一个新对象;
  2. 新对象的内部【prototype】特性被赋值为构造函数的prototype
  3. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
  4. 执行构造函数中的代码(为这个新对象添加属性);
  5. 返回新对象。

    函数表达式也可以是构造函数

    ```javascript let Person =function (name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { console.log(this.name); } };

let p = new Person(‘Ethan’, 24, ‘ java’)

console.log(p.name); // Ethan

  1. **在实例化时 如果不想传参数,那么也可省略括号 只要有new操作符就可以**
  2. ```javascript
  3. function Person(){
  4. this.name = "gaojian"
  5. this.sayName = function(){
  6. console.log(this.name)
  7. }
  8. }
  9. let person1 = new Person();
  10. let person2 = new Person;
  11. person1.name() //"gaojian"
  12. person2.name() //"gaojian"

其实person1和person2 每个对象都是Object的实例 同事也是 Person的实例 用instanceof 可以查看结果

  1. function Person(){
  2. this.name = "gaojian"
  3. this.sayName = function(){
  4. console.log(this.name)
  5. }
  6. }
  7. let person1 = new Person();
  8. let person2 = new Person;
  9. console.log(person1 instanceof Object); //true
  10. console.log(person2 instanceof Object); //true
  11. console.log(person1 instanceof Person); //true
  12. console.log(person2 instanceof Person); //true

构造函数也是函数 与普通函数的区别

构造函数与普通函数的最大区别就是调用方式不同,任何函数只要使用new 操作符调用就是构造函数,而不用new调用就是普通函数。
区别:

  1. 调用方式“创建当前类的实例对象”
  2. 在构造函数中This指向这个实例对象 构造函数中this.xxx =xxx 都是给实例对象设置属性的私有属性和方法 自己单独声明的变量 和实例没有关系
  3. 如果构造函数中没有return 或返回的是原始类型,则把场景的实例对象返回,只有自己手动返回的对象,才以自己的返回值为主

作为构造函数

  1. function Person(name, age) {
  2. this.name = name || "gaojian";
  3. this.age = age;
  4. this.sayName = function () {
  5. console.log(this.name + this.age)
  6. }
  7. }
  8. let person1 = new Person("tom", 33);
  9. let person2 = new Person('', 33)
  10. person1.sayName()
  11. person2.sayName()

作为函数调用

  1. function Person(name, age) {
  2. this.name = name || "gaojian";
  3. this.age = age;
  4. this.sayName = function () {
  5. console.log(this.name + this.age)
  6. }
  7. }
  8. Person("kill", 22) //此时添加到window对象上
  9. window.sayName()

在另一个对象的作用域上调用

  1. let obj = Object.create(null)
  2. Person.call(obj,"hanmei",33)
  3. obj.sayName() //hanmei33

构造函数的问题

主要问题在于 其定义的方法会在每个实例上都创建一遍 特别是函数 每次定义函数时 都会初始化一个对象 解决这个问题可以把函数转移到构造函数外部:

  1. function Person(name, age, job) {
  2. this.name = name;
  3. this.age = age;
  4. this.job = job;
  5. this.sayName = sayName;
  6. };
  7. function sayName() {
  8. console.log(this.name);
  9. }
  10. let p = new Person('Ethan', 24, 'java');
  11. p.sayName(); // Ethan

但这样做全局作用域也被搞乱了 而且对象如果有多个方法那都需要定义在全局作用域里 解决这个问题那就是需要原型模式 原型继承来解决

练习题(珠峰)
知识点:

  1. 每次new 都是创建单独的实例对象 f1 !== f2
  2. 在构造函数中This指向这个实例对象 构造函数中this.xxx =xxx 都是给实例对象设置属性的私有属性和方法 自己单独声明的变量 和实例没有关系
  3. 设置的私有属性,两个实例 即使同名属性 也都是自己私有的 f1.say !== f2.say

**

  1. function Fn(x, y) {
  2. let sum = 10;
  3. this.total = x + y;
  4. this.say = function () {
  5. console.log(`我计算的和是:${this.total}`);
  6. };
  7. }
  8. let res = Fn(10, 20); //普通函数执行
  9. window.say()
  10. let f1 = new Fn(10, 20); //构造函数执行
  11. let f2 = new Fn;
  12. console.log(f1.sum);
  13. console.log(f1.total);
  14. console.log(f1.say === f2.say);


image.png**