通过例子深入理解javascript中的new操作符

时间:2022-11-14 13:47:08

1.首先看一道题目

 function Cat(name,age){
this.name=name;
this.age=age;
}
console.log(new Cat('miaomiao',18));
//Cat {name: "miaomiao", age: 18}

2.那么这里面的this指的是什么呢

 function Cat(name,age){
console.log(this);//Cat {}
this.name=name;
this.age=age;
}
new Cat('miaomiao',18);

3.我们发现this是一个名为Cat的空对象,那么后两句(this.name=name;this.age=age)就相当于var Cat={};Cat.name=name;Cat.age=age;是这样的么我们来试一下

 function Cat(name,age){
var Cat = {};
Cat.name=name;
Cat.age=age;
}
console.log(new Cat('miaomiao',18));
//Cat {}

4.发现并不是那么回事,这是为什么,在javascript中如果没有return 那么函数就会默认return this为了验证我们在函数最后面return Cat即可

 function Cat(name,age){
var Cat = {};
Cat.name=name;
Cat.age=age;
return Cat;
}
console.log(new Cat('miaomiao',18));
//Object {name: "miaomiao", age: 18}

5.好像成功了,我们和之前对比一下

 function Cat(name,age){
this.name=name;
this.age=age;
}
console.log(new Cat('miaomiao',18));
//Cat {name: "miaomiao", age: 18}

6.函数的作用我们理解的差不多,下面开始探索NEW,试想如果我们不返回对象而是返回null或者其他类型的会是什么效果呢

 function Cat(name,age){
var Cat = {};
Cat.name=name;
Cat.age=age;
return undefined//或者null 123 '123'等非对象;
}
console.log(new Cat('miaomiao',18));//Cat{}

7.其他的一律输出空对象

那么我们试着写一个类似new的函数功能

 function Cat(name,age){
this.name=name;
this.age=age;
}
function New(){
var obj={};
var res=Cat.apply(obj,arguments);
return typeof res==='object'?res:obj
}
console.log(New('mimi',18))
//Object {name: "mimi", age: 18}

8.这样就大功告成了么  当然不是,我们接着往下看

  function Cat(name,age){
this.name=name;
this.age=age;
}
Cat.prototype.sayHi=function(){
console.log('hi')
}
function New(){
var obj={};
var res=Cat.apply(obj,arguments);
return typeof res==='object'?res:obj
} console.log(new Cat('mimi',18).sayHi())
console.log('-------------');
console.log(New('mimi',18).sayHi()); VM841:7 hi
VM841:15 undefined
VM841:16 -------------
VM841:17 Uncaught TypeError: New(...).sayHi is not a function(…)

9.红色的事报错,说明new操作不仅仅关注函数的本身 还关心他的原型 prototype

上面分析了那么多,现在进入正题。

  普通对象是没有prototype属性的,只有隐藏属性__proto__(IE上也有该隐藏属性,但是使用obj.__proto__不能输出东西,所以建议不要使用__proto__属性)。而函数对象则两者兼有。prototype属性指向的是函数对象的原型对象,对象的__proto__属性是创建实例对象的时候对应的函数对象的原型对象。

  function Cat(name,age){
this.name=name;
this.age=age;
}
Cat.prototype.sayHi=function(){
console.log('hi')
}
function New(){
var obj={};
obj.__proto__=Cat.prototype;
var res=Cat.apply(obj,arguments);
return typeof res==='object'?res:obj
} console.log(new Cat('mimi',18).sayHi())
console.log('-------------');console.log(New('mimi',18).sayHi()); VM844:7 hi
VM844:16 undefined
VM844:17 -------------
VM844:7 hi
VM844:17 undefined
undefined

10.ok大功告成