一、js中new一个对象的过程
首先了解new做了什么,使用new关键字调用函数(new ClassA(…))的具体步骤:
1、创建一个新对象:
var obj = {};
2、设置新对象的constructor属性为构造函数的名称,设置新对象的__proto__属性指向构造函数的prototype对象;
obj.__proto__ = ClassA.prototype;
3、使用新对象调用函数,函数中的this被指向新实例对象:
ClassA.call(obj); //{}.构造函数()
4、将初始化完毕的新对象地址,保存到等号左边的变量中
注意:若构造函数中返回this或返回值是基本类型(number、string、boolean、null、undefined)的值,则返回新实例对象;若返回值是引用类型的值,则实际返回值为这个引用类型。
var foo = "bar";function test () { this.foo = "foo";}new test(); //test中的this指新对象,并未改变全局的foo属性console.log(this.foo); // "bar"console.log(new test().foo); // "foo";
二、用原生JS实现new方法
// 通过分析原生的new方法可以看出,在new一个函数的时候,// 会返回一个func同时在这个func里面会返回一个对象Object,// 这个对象包含父类func的属性以及隐藏的__proto__function New(f) { //返回一个func return function () { var o = { "__proto__": f.prototype}; f.apply(o, arguments);//继承父类的属性 return o; //返回一个Object }}
首先写一个父类方法(包含参数name,age):
function Person(name,age){ this.name = name; this.age = age;}
//new一个Person的实例p1做研究对比var p1 = new Person("Richard", 22);//此时p1包含name、age属性,同时p1的__proto__指向Person的prototypep1.name;//Richardp1.age;//22
通过自定义New方法创建一个实例对象p2:
var p2 = New(Person)("Jack",25);p2.name;//Jackp2.age;//25
此时p2 instanceof Person 返回的是true;
Person.prototype.gender ="male";p1.gender//malep2.gender//male
三、优先级问题
:小括号(xxx) > 属性访问. > new foo() > foo()
注意new Foo()优先级高于Foo();
function getName(){ console.log(1)}function Foo() { this.getName = function () { console.log(2); }; return this;}Foo.getName = function () { console.log(3);};//先从.属性访问符号开始往前面找一个最近的对象,同时注意new Foo()优先于Foo();var a=new Foo.getName();//3; 属性.的优先级高于new foo(),所以===new (Foo.getName)();返回Foo.getName类型的实例var b=new Foo().getName();//2; new foo()的优先级高于foo(),所以就相当于new foo()的属性,===(new Foo()).getName();返回undefinedvar c=new new Foo().getName();//2; new foo()优先级低于属性.,所以其实相当于就是new一个new foo()的getName属性函数,===new (new Foo().getName)();返回Foo.getName类型的实例new Date().getTime();//===((new Date()).getTime)()(new Date).getTime();//===((new Date()).getTime)()new Date.getTime();//Uncaught TypeError: Date(...).getTime is not a function;===new (Date.getTime)()
需要注意的是:new Date 其实也是正确的,和new Date()一样