[TOC]

(一) new关键字的作用

1. 自动创建临时对象 ( 在函数内部使用this可以访问到这个临时对象 )

2. 自动绑定该Function对象的原型 ( 统一叫做prototype )

3. 把传入的参数赋给给临时对象

4. 自动return这个临时对象

<script>
    function MadeCat(name, age) {
        // 查看this.__proto__,说说this指向了谁
        this.name = name;
        this.age = age;
    }
    var cat = new MadeCat('小白', 2);
    cat.__proto__ === MadeCat.prototype;


    // 手动实现上面的步骤,new关键字就是做了以下这些事情
    function MadeCat2(name, age) {
        // 1. 创建临时对象obj
        var obj = new Object();
        // 2. 绑定临时对象obj的原型对象为MadeCat2的原型对象
        obj.__proto__ = MadeCat2.prototype;
        // 3. 把传入的name和age赋给obj
        obj.name = name;
        obj.age = age;
        // 4. 返回临时对象obj
        return obj;
    }
    // 调用MadeCat2得到新的对象,对比上面的例子,谈谈new关键字都起了什么作用,不使用new来创建对象行不行
    var cat2 = MadeCat2('小黑', 1);
    cat2.__proto__ === MadeCat2.prototype;
</script>

(二) call、apply 和bind有什么区别?

三者都会改变this的指向, 区别:

1. call 和 apply 的功能相同,区别在于传参的方式不一样:

  1. call的第一个参数是this要指向的对象, 第二个,第三个….都是调用函数需要的参数。
  2. apply第一个参数是this要指向的对象, 第二个参数是数组或类数组。

    <script>
    // 1. 声明两个变量和一个函数
    var username = '张三';
    var age = 18;
    
    function say(provice, city) {
      console.log('this=', this);
      console.log(`我来自${provice}${city}`);
      console.log(`我叫${this.username},今年${this.age}岁`);
    }
    
    // 2. 创建一个对象
    var person = {
      username: '老胡',
      age: 100
    };
    
    say('广东', '深圳');
    
    // 3. 使用call改变this的指向:第一个参数是this将要指向的对象, 第二参数,第三个参数.....,这些参数函数调用需要传入的参数
    say.call(person, '广西', '贵港');
    
    // 4. 使用apply改变this的指向:第一个参数是this将要指向的对象, 第二参数是个数组,数组放入的是函数需要的参数
    say.apply(person, ['陕西', '西安']);
    </script>
    

    2. bind 和 call/apply 有一个很重要的区别,

  3. 一个函数被 call/apply 的时候,会直接调用,但是 bind 会创建一个新函数, 不会直接调用

  4. 当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this, 新函数的调用和原来函数的调用一模一样,除了this的指向不一样之外

    <script>
    // 1. 声明两个变量和一个函数
    var username = '张三';
    var age = 18;
    
    function say(provice, city) {
      console.log('this=', this);
      console.log(`我来自${provice}${city}`);
      console.log(`我叫${this.username},今年${this.age}岁`);
    }
    
    // 2. 创建一个对象
    var person = {
      username: '老胡',
      age: 100
    };
    
    say('广东', '深圳');
    
    // 3. 使用bind的方法创建(得到)一个新函数, 这个新函数不会立即调用, 参数是this要指向的对象
    var say2 = say.bind(person);
    
    // 4. 调用新函数, 出入所需要参数 
    say2('广东', '深圳');
    
    // say.bind(person)('广东', '深圳'), 两步拼成一步来操作
    </script>
    

    (三) this的指向

    1. 方法调用, 谁调用指向谁

    ```javascript

    <a name="HYejK"></a>
    #### 
    <a name="tunTC"></a>
    ### 2. 函数里的函数调用
    ```javascript
    <script>
        var age = 38;
        var obj = {
            age: 18,
            getAge: function() {
                var fn = function() {
                    console.log(this);
                    console.log(this.age);
                };
                // this指向了谁? 指向了window
                fn();
            }
        };
        obj.getAge();
    </script>
    

    3. 构造函数中的this指向创建出的对象。

    <script>
        function MadeCat(name, age) {
            // this指向了谁?this指向了MadeCat的实例,因为this.__proto__ === MadeCat.prototype 为true, 
            // 实例.__proto__ === MadeCat.prototype也是true, 说明this跟实例是同一个对象
            console.log(this);
            debugger;
            this.name = name;
            this.age = age;
        }
        var cat = new MadeCat('小白', 2);
    </script>
    

    4. 存在call、apply和bind这三个方法的时候, this指向了传入的对象

    <script>
        var username = '张三';
        var age = 18;
    
        function say(provice, city) {
            console.log('this=', this);
            console.log(`我来自${provice}${city}`);
            console.log(`我叫${this.username},今年${this.age}岁`);
        }
    
        var person = {
            username: '老胡',
            age: 100
        };
    
        // 调用say()时,this指向了谁?
        say('广东', '深圳');
        // 使用say.call()时,this指向了谁
        say.call(person, '广西', '贵港');
        // 使用apply.call()时,this指向了谁
        say.apply(person, ['广西', '贵港']);
    </script>