美文网首页
JavaScript构造器详解

JavaScript构造器详解

作者: JRucker | 来源:发表于2018-07-23 14:52 被阅读0次

    我们都知道JavaScript不像其他语言,它没有class关键字,但是它有跟function非常相似的构造函数。这篇文章我们一起来详细地了解JavaScript构造函数如何构造对象。著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。

    构造函数跟普通函数非常相似,但是我们通过new关键字来使用它们。主要有两种类型的构造函数,native构造函数(Array,Object)它们可以在执行环境中自动生成,还有自定义的构造函数,你可以定义自己的方法和属性。著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。

    当你想要创建很多相似的对象(拥有相同的属性和方法)的时候,使用构造函数是非常有效的。大部分程序员都遵循公约,使用大写字母开头来将构造函数和普通函数区分开。看看下面的代码。著作权归作者所有。
    商业转载请联系作者获得授权,非商业转载请注明出处。

    function Book() { 
      // unfinished code
    } 
    var myBook = new Book();
    

    最后一行代码创建了一个Book对象,并把它赋值给变量;这样完成之后,即使Book构造器没有做任何操作,myBook也是Book实例。正如你看到的,除了首字母大写和使用new关键字之外,构造函数和普通函数并没有什么区别。

    判断实例的类型


    判断某个对象是否为某种实例,我们可以使用instanceof操作符:

    myBook instanceof Book // => true 
    myBook instanceof String // => false
    

    注意:如果右边不是一个函数的实例,那么将会报错:

    myBook instanceof {}; // => TypeError: invalid 'instanceof' operand ({})
    

    另一种方法是使用constructor属性,所有对象实例都有一个constructor属性,这个属性指向创建它的构造函数。

    myBook.constructor == Book; // => true
    

    就像myBookconstructor指向Book一样。 所有对象都从它们的原型上继承了constructor这个属性:

    var s = new String("text"); s.constructor === String; // => true 
    "text".constructor === String; // => true 
    var o = new Object(); o.constructor === Object; // => true 
    var o = {}; o.constructor === Object; // => true 
    var a = new Array(); a.constructor === Array; // => true 
    [].constructor === Array; // => true
    

    尽管使用constructor可以用来检测实例类型,但是建议还是使用instanceof方法。因为constructor属性是可以被重写的..用起来不太靠谱。

    自定义构造函数



    构造函数就像饼干印模。同一印模制作出来的,都是同一个diao样(男人没一个好东西也是这个道理)。
    function Book(name, year) { 
      this.name = name; 
      this.year = '(' + year + ')'; 
    }
    

    Book构造器需要两个参数,当使用new关键字构造对象时,会把两个形参传给Book对象的nameyear

    var firstBook = new Book("Pro AngularJS", 2014); 
    var secondBook = new Book("Secrets Of The JavaScript Ninja", 2013); 
    var thirdBook = new Book("JavaScript Patterns", 2010); 
    console.log(firstBook.name, firstBook.year); 
    console.log(secondBook.name, secondBook.year); 
    console.log(thirdBook.name, thirdBook.year);
    
    console-log.png

    如你所见,我们可以通过传不同参数,快速创建另一本书。JavaScript的Array(),Date()也是这个道理。

    Object.defineProperty 方法



    Object.defineProperty 方法可以在构造器中被使用来配置属性。
    function Book(name) { 
      Object.defineProperty(this, "name", { 
        get: function() { 
          return "Book: " + name; 
        }, 
        set: function(newName) { 
          name = newName; 
        }, 
        configurable: false 
      }); 
    } 
    var myBook = new Book("Single Page Web Applications"); 
    console.log(myBook.name); // => Book: Single Page Web Applications 
    // we cannot delete the name property because "configurable" is set to false 
    delete myBook.name; 
    console.log(myBook.name); // => Book: Single Page Web Applications 
    // but we can change the value of the name property 
    myBook.name = "Testable JavaScript"; 
    console.log(myBook.name); // => Book: Testable JavaScript
    

    上面的代码中是调用了祖先的方法。它提供了gettersetter接口。getter方法负责返回封装的值,setter方法接受参数,并把值赋给属性。当我们在某个属性上操作存取时,调用的就是这两个方法。通过配置configurable,我们可以设置该值能否被删除。

    对象字面量表示法是首选的构造函数



    JavaScript语言九种内建的构造器:Object(), Array(), String(), Number(), Boolean(), Date(), Function(), Error() 以及 RegExp()。当我们需要创建这些值的时候,我们可以自由选择使用字面量或者构造器。但是相同情况下,字面量对象不仅易读,而且运行速度更快,因为他们可以在解析的时候被优化。所以当你需要使用简单对象的时候就使用字面量吧。
    // a number object 
    // numbers have a toFixed() method 
    var obj = new Object(5); 
    obj.toFixed(2); // => 5.00 
    // we can achieve the same result using literals 
    var num = 5; num.toFixed(2); // => 5.00 
    // a string object // strings have a slice() method 
    var obj = new String("text"); 
    obj.slice(0,2); // => "te" // same as above 
    var string = "text"; 
    string.slice(0,2); // => "te"
    

    使用new关键字是必不可少的



    记得使用构造器的时候要用new关键字,如果你不小心忘记了,那么构造器中的this指向的是global对象(浏览器中默认为window)。
    function Book(name, year) { 
      console.log(this); 
      this.name = name; 
      this.year = year; 
    } 
    var myBook = Book("js book", 2014); 
    console.log(myBook instanceof Book); 
    console.log(window.name, window.year); 
    var myBook = new Book("js book", 2014); 
    console.log(myBook instanceof Book); 
    console.log(myBook.name, myBook.year);
    

    运行结果如下

    console-log-2.png
    如果是在严格模式下,上面的代码将会抛出错误,因为严格模式不允许我们不使用new关键字调用构造器。

    适用范围更高的构造器



    为了解决可能会忘记使用new关键字的风险,我们可以通过判断this的值创建适用范围更高的构造器。
    function Book(name) { 
      if (!(this instanceof Book)) { 
      // the constructor was called without "new". 
      return new Book(name); 
      } 
    }
    

    加上这段代码之后,我们就可以‘肆无忌惮’地使用构造器了。

    function Book(name, year) { 
      if (!(this instanceof Book)) { 
        return new Book(name, year); 
      } 
      this.name = name; 
      this.year = year; 
    } 
    var person1 = new Book("js book", 2014); 
    var person2 = Book("js book", 2014); 
    console.log(person1 instanceof Book); // => true 
    console.log(person2 instanceof Book); // => true
    
    

    相关文章

      网友评论

          本文标题:JavaScript构造器详解

          本文链接:https://www.haomeiwen.com/subject/izfjmftx.html