有意思的一道题

  今天有同学问了这么一道题,倒是有点意思,如下:

    function Person(name) {
      this.getName = function () {
        return name;
      }
      this.setName = function (name) {
        name = name;
      }
    }
    var person1 = new Person("wayne");
    console.log(person1.getName()); // wayne
    var person2 = new Person("hedy");
    console.log(person2.getName()); // hedy 
    console.log(person1.getName()); // wayne

    很简单,就是为什么最后的结果是这样的。 最后一个结果为什么不是hedy。

  

  于是,我给他举了下面这样的一个例子:

   function Person(obj) {
      this.getName = function () {
        return obj.name;
      }
      this.setName = function (obj) {
        name = obj.name;
      }
    }
    var obj = {
      name: "wayne"
    };
    var person1 = new Person(obj);
    console.log(person1.getName()); // wayne
    obj.name = "hedy";
    var person2 = new Person(obj);
    console.log(person2.getName()); // hedy 
    console.log(person1.getName()); // hedy

  到这里,他还是不太明白,所以,我可以给他解释一下了。

  在new的过程中,实际上也是在调用函数,且调用函数时就会创建一个新的函数作用域,对于第一个程序,实际上涉及到了闭包的概念,因为构造函数内部的name还在引用这个构造函数,所以形成了闭包,即使在new之后,这个构造函数中的name依然会保存,而在getName()的过程中,就去寻找这个name; 而再new另外一个Person的时候,实际上又进入了一个新的函数作用域,这个函数作用域同样又保存了新的name,所以第一个程序也就不难理解了。

  而第二个程序,因为我创建了一个对象,在对象传入函数的过程中,实际上是传递的引用,即这个对象始终都在堆中的同一个内存里,所以说修改了对象之后,getName()得到的值就始终一样了 。

  接着,他又问我,第一个程序中在person1.getName()之后,这里已经将getName()调用了,那么构造函数中的name不是应该释放了吗?为什么最后调用还是可以找到呢? 我又写了下面的这个函数:

    function Person(name) {
      this.getName = function () {
        return name;
      }
      this.setName = function (name) {
        name = name;
      }
    }
    var person1 = new Person("wayne");
    alert(person1.getName()); // wayne
    var person2 = new Person("hedy");
    alert(person2.getName()); // hedy 
    person1.getName = null;

  这样,getName函数就不会对Person构造函数进行引用了,这时,实际上Person中的name就会被释放了。  

       看似简单的一道题,实际上涉及到了构造函数的本质、基本数据类型和引用类型在传参的区别、作用域、闭包等等概念,还是非常不错的。

原文地址:https://www.cnblogs.com/zhuzhenwei918/p/8969927.html