Javascript中,实例化一个对象,会用到new关键字。
经常有人会问我,对于一个函数,什么时候该使用new关键字。
在回答这个问题之前,需要先了解清楚new的本质,在调用new Function的时候,new做了什么操作。
先看如下代码:
// 定义类 类名字是 classA
function classA(){
this.name=1;
}
classA.prototype.show = function(){
alert(this.name);
};
// 用new实例化
var b = new classA();
b.show();
在
var b = new classA();
这句中,new做了以下几件事情。
1、创建一个新的对象,这个对象的类型是object;
2、查找class的prototype上的所有方法、属性,复制一份给创建的Object
3、将构造函数classA内部的this指向创建的Object
4、创建的Object的__proto__指向class的prototype
5、执行构造函数class
6、返回新创建的对象给变量b
这个流程应该比较好理解的。这里再解释一下:
1、构造函数:我们一般把new 后面的函数称为构造函数,如new classA(),其中classA就为构造函数
2、第四点的__proto__,可能比较难理解。
每个对象都会在其内部初始化一个属性,就是__proto__,可以在chrome中的调试器里写个对象查看下。当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
当我们调用b.show()时,首先b中没有show这个属性,于是,它就需要到它的__proto__中去找,也就是ClassA.prototype,
而我们在上面定义了ClassA.prototype.show=function(){}; 于是,就找到了这个方法。
再用下面的代码来理解
var b = {}
b.__proto__ = ClassA.prototype
ClassA.call(b)
最后再用一句话总结:new关键字以ClassA()为模板创建了一个新的对象,它复制了ClassA构造器中的所有成员变量,同时this指向新创建的对象。
有2点需要注意:
1、如果构造函数内没有返回值,则默认是返回this(当前上下文),要不然就返回任意非原始类型值。
2、如果不用new关键字,如
var b = classA();
则classA值会返回undefined,并且this(执行上下文)是window对象。
也就是说如果你不new的话,this指的就是window全局对象了。
如果要理解这点,需要理清楚this的指向。
this的指向:
1、总的来说,this在函数内部使用,用来引用包含函数的对象,而不是函数本身。
2、当this值的宿主函数被封装在另一个函数的内部或在另一个函数的上下文中被调用时,this值将永远是对head对象的引用(即全局window对象)
3、使用new关键字调用构造函数时,this引用“即将创建的对象”
如下面代码:
// 定义类 类名字是 classA
function classA(){
this.name=1;
}
//执行classA
classA();
//看下name是undefined还是1
name //返回1
看到这里,相信绝大多数人应该都理解了new的用法了。
new的疑惑
// 加不加new结果都一样
var obj = new Function('var temp = 100;this.temp = 200;return temp + this.temp;');
alert(typeof(obj)); // function
alert(obj()); // 300
var obj = Function('var temp = 100;this.temp = 200;return temp + this.temp;');
alert(typeof(obj)); // function
alert(obj()); // 300
var d=Date();
alert(d);
var reg1 = new RegExp('^hello$');
var reg2 = RegExp('^hello$');
reg1.test('hello'); // true
reg2.test('hello'); // true
console.log(typeof reg1); // object
console.log(typeof reg2); // object
测试发现使用或不使用new,最后返回的都是正则对象,且typeof它们都是object。下面都情况又不一样了
var str1 = new String(1);
var str2 = String(1);
var num1 = new Number('1');
var num2 = Number('1');
var bool1 = new Boolean(1);
var bool2 = Boolean(1);
alert(typeof str1); // object
alert(typeof str2); // string
alert(typeof num1); // object
alert(typeof num2); // number
alert(typeof bool1); // object
alert(typeof bool2); // boolean
或者
function person(name,age){
this.name=name;
this.age=age;
}
var p1=person('zhangsan',30);
alert(p1);//undefined
var p2=new person('zhangsan',30);
alert(p2);//object
JavaScript是一门基于原型的语言,但它却拥有一个 new 操作符使得其看起来象一门经典的面对对象语言。那样也迷惑了程序员,导致一些有问题的编程模式。其实你永远不需要在JavaScript使用 new Object()。用字面量的形式{}去取代吧。不要使用 new Array() ,而代之以字面量[]。JavaScript中的数组并不象Java中的数组那样工作的,使用类似Java的语法只会让你糊涂。不要使用 new Number, new String, 或者 new Boolean。这些的用法只会产生无用的类型封装对象。不要使用 new Function 去创建函数对象。用函数表达式更好。比如:
frames[0].onfocus = new Function("document.bgColor='antiquewhite'") ;
应该
frames[0].onfocus = function () {document.bgColor = 'antiquewhite';};
当你这样写的时候
myObj = new function () {
this.type = 'core';
};
你应该
myObj = {
type: 'core'
};
原则很简单: 唯一应该要用到new操作符的地方就是调用一个构造器函数的时候。当调用一个构造器函数的时候,是强制要求使用new的