js杂谈new的故事

粗略的看过了<<javascript高级程序设计>>,感觉收获很多,于是乎,拿起各家公司的javascript面试题,顿时被试题强暴了,真心感觉自己还是对javascript有太多不明白,javascript的语法宽松,就导致有许多特殊的地方,javascript有基于原型的面向对象。也是非常值得玩味的地方。

今天,我们来说说new。看代码

var C = function(name){
    this.name = name;
    }
var Person = new C('11');
//var Person = new C; 这种调用方式其实就是var Person = new C(),不传参数
alert(Person.name)

书面关于new的解释如下:
当使用new关键字来调用构造函数时,执行上下文从全局对象(window)变成一个空的上下文,这个上下文代表了新生成的实例。

网站上也有给出介绍

new的过程可以分为3步

1.创建一个新对象,var Person

2.让实例Person的_proto_属性指向C.prototype

3.C.call(Person)

第2步,我们会在谷歌等调试程序中看到,第3步其实就是借用了C的构造器,使得实例拥有它的成员

上图是谷歌的断点调试,我们可以看到,Person中的构造器是C,它继承了C的name属性。因为C是一个function,本质上是Object。所以C的原型应该是Object,那Person的_proto_属性也指向它。

可能网站的解释比较通俗一点,我们再来看书面的解释,大家注意一点,那就是执行上下文从全局对象(window)变成一个空的上下文,为什么执行上下文开始会是全局对象了,看代码吧

var name = 1
var C = function(){
    var name = 2;
    var K = function(name){
        this.name = name;
        }
    }
var Person = new C();
C();

我们还有断点调试,查看一下K中this到底是什么

执行var Person = new C();时this指向C

执行C()时,this指向window

this的指向问题,<<javascript高级程序设计>>中定义如下

在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this就等于那个对象。

如下代码

var name = 1;
var C = function(){
    var name = 2;
    function B(){
        alert(name);
        }
    B();
    }
C();

显示是2,函数里面套函数,大家最直观的感觉就是闭包。没错,是闭包。ok,修改一下代码,如下会输出什么

var name = 1;
var C = function(){
    var name = 2;
    function B(){
        alert(this.name);
        }
    B();
    }
C();

这个显示1,我这里讲一下,我当时分析的一个错误观点。理解透彻的朋友可以跳过。
B是在C函数中声明的,意味着B存在于C函数的上下文中,由于有一种在全局环境中定义的属性和方法,都可以使用window.XX来调用,所以当时的我天真的以为B是C的一个方法,这个就大错特错了。很明显B如此声明根本就不是C的方法,根据<<javascript高级程序设计>>中对this的定义,B方法中的this,应当属于把它当成方法调用的那个对象。肯定不是C,所以答案不是2.

书中对B函数的调用者为什么是全局,并没有分析太透彻,我在有一页中看到在之中的匿名函数调用者也是全局,自执行的函数也是。再看代码

var name = 1;
var C = function(){
    var name = 2;
    function B(){
        alert(this.name);
        }
    B();
    }
var Person = new C();

还是显示1,书中讲到new运算符改变了函数的执行上下文。执行上下文从全局变量变成了一个空上下文,这个上下文代表了新生成的实例。当程序执行到function B(){}的最后一个}时,this是指向Person实例,也就是它的构造器C,但当程序执行B()时,由于B并不是C的方法,所以B中的this又指向了window,大家可能动手试一试。

这里我们也就明白了书中讲new的过程了。

ok,下面再补一个代码

var C = function(){
    var klass = function(){
        this.init.apply(this,arguments);
        };
    klass.prototype.init = function(){
        alert(1);
        };
    return klass;
    }
var Person = new C();

这是一种设计模式,<<javascript高级程序设计>>中叫寄生构造函数模式,如果当时读这个,我真心不会有太多印象,死记模式的优缺点不是件好事。
在这种,既return,又new的节奏,可能让人摸不着头脑,仔细分析。在构造函数不返回值的情况下,默认返回新对象的实例,这里通过在构造函数的末尾添加return,相当于重写的返回值,这里我们很清楚,klass跟构造器C根本没有什么关系。之前我们也都提到了。

ok,时间不多,字数刚好。以上是本人的一点小研究,有不对的地方,大家指点。

结束语:

javascript是座冰山,我能看到的只是冰山一角。

原文地址:https://www.cnblogs.com/wumadi/p/3029812.html