构造函数 ,是一种特殊的方法。主要用来为对象成员变量赋初始值,总与new运算符一块儿使用在建立对象的语句中,对于JavaScript的内置对象Number()、String()、Boolean()、Object()、Array()、Function()、Date()、RegExp()、Error()等都是构造函数;
bash
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayHello = function(){
console.log(this.name+":Hello!");
};
}
var person1 = new Person("lilei", 26, "Teacher"); //实例对象 person1
var person2 = new Person("xiaom", 27, "Doctor"); //实例对象 person2
复制代码
构造函数与其余函数的惟一区别,就在于调用它们的方式不一样。构造函数毕竟也是函数,不存在定义构造函数的特殊语法。任何函数,只要经过 new 操做符来调用,那它就能够做为构造函数函数
上一节咱们说到在JavaScript中,几乎全部的事物都是对象:对象只是带有属性和方法的特殊数据类型
可是基本类型值不是对象,于是从逻辑上讲它们不该该有方法,实际上咱们建立 String 类型时后台自动作了一些处理:this
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;
复制代码
基本类型值不是对象,只有引用类型是对象,可是 咱们可让String成为引用类型:spa
var s1 = new String("some text");
复制代码
当咱们手动new一个字符串s1的时候,s1既是String又是引用类型,因此他是一个对象;prototype
引用类型与基本包装类型的主要区别就是对象的生存期。使用 new 操做符建立的引用类型的实例, 在执行流离开当前做用域以前都一直保存在内存中。而自动建立的基本包装类型的对象,则只存在于一 行代码的执行瞬间,而后当即被销毁;设计
要建立 Person 的新实例,必须使用 new 操做符,调用构造函数建立对象通过了如下几个过程:指针
在前面例子中,person1 和 person2分别保存着Person的一个不一样的实例。这两个对象都有一个constructor(构造函数) 属性,该属性指向 Person:code
console.log(person1.constructor == Person); //true
console.log(person2.constructor == Person); //true
复制代码
在JS中判断一个变量的类型常常会用 typeof 运算符,可是在使用 typeof 运算符来判断引用类型时,不管引用的是什么类型的对象,它都返回"object"。因此在判断对象的类型时咱们可使用 instanceof 运算符:对象
console.log(person1 instanceof Object); //true
复制代码
使用构造函数时每一个方法都要在每一个实例上从新建立一遍:ip
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayHello = function(){
console.log(this.name+":Hello!");
};
//this.sayHello = new Function('console.log(this.name+":Hello!")')
}
复制代码
new Function与声明函数在逻辑上是同样的,因此每次实例化Person对象时,sayHello 方法也是一个新实例,因此:
console.log(person1.sayName == person2.sayName); //false
复制代码
注意:person1.sayName 与person1.sayName()不同,person1.sayName()是指函数返回值,person1.sayName是指函数自己;
建立两个完成一样任务的 Function 实例的确没有必要,所以,咱们能够经过把函数定义转移到构造函数外部来解决这个问题。例如:
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayHello = sayHello;
}
function sayHello(){
console.log(this.name+":Hello!");
}
复制代码
这样将 sayName 属性设置成指向全局函数 sayName() 的指针。sayName()只被实例化一次; 可是若是对象须要定义不少方法,那么就要定义不少个全局函数。并且在全局做用域中定义的函数实际上只被某个对象调用,这样不符合全局函数的理念。咱们这个自定义的引用类型也丝毫没有封装性可言。好在这些问题能够经过使用原型模式来解决。因此下一节《 prototype(原型)》
《JavaScript 高级程序设计》中文译本 第三版