最近看下了方方大佬在知乎上一篇将new的文章很有启发,没有从面向对象的角度去思考,但却有着更底层的思考,我给自己总结记录一下。
1、那个经典的例子开始说起
首先我们创建一个包含人类对象,它包含一些属性和方法
// person 对象
var person = {
name: 'join',
age: 12,
say: function(){
console.log('say')
},
jump: function(){
console.log('jump')
}
}
2、现在我们需要一百个这样的person对象
下面用最笨的一个方法来实现以下
var persons = []
var person
for(var i=0; i<100; i++){
person = {
name: 'join',
age: 12,
say: function(){
console.log('say')
},
jump: function(){
console.log('jump')
}
}
persons.push(pseron)
}
这样写看着很傻是吧,如果你对原型链有一个了解的话,那么这些方法可以用挂在原型链上,来解决重新创建的问题,来看一下改进版本。
var persons = []
var personShare = {
say: function(){
console.log('say')
},
jump: function(){
console.log('jump')
}
}
for(var i=0; i<100; i++){
person = {
// 每个人的name和age都是不一样的,所以写在这里了
name: 'join',
age: 12,
}
person.__proto__ = personShare
// __proto__是一个隐藏属性,平时并不建议这么使用
// person.__proto__.say = person.say = personShare.say
// person.__proto__.jump = person.jump = personShare.jump
persons.push(pseron)
}
3、优雅的改进一下
然后这边可以发现的是不是将person分成两部分写起来不太优雅,接下来在进行一点优雅版本的改进,用一个函数将两部分合起来
person.prototype = {
say: function(){
console.log('say')
},
jump: function(){
console.log('jump')
}
}
function person(name, age) {
//先来创建一个临时对象
var temp = {}
// 加上属性
temp.name = name
temp.age = age
//加上方法
temp.__proto__ = person.prototype
return temp
}
// 这样看起来起来是不是就很简洁了
var persons = []
var name = ['a','b','c', ...]
var age = [1,2,3, ...]
for(var i=0; i<100; i++){
persons.push(person(name[i], age[i]))
}
4、new 出来啦!!!
上面有这样一句代码
persons.push(person(name, age))
这里我们可以把person(name, age)
当作new Person(name ,age)
来看的话,在出来理解下是不是感觉出其的相似,就是这样的,站在这个视角上,new 帮我们做了这几个事情
- 不用创建临时对象,因为 new 会帮你做(你使用「this」就可以访问到临时对象);
- 不用绑定原型,因为 new 会帮你做(new 为了知道原型在哪,所以指定原型的名字为 prototype);
- 不用 return 临时对象,因为 new 会帮你做;
- 不要给原型想名字了,因为 new 指定名字为 prototype。
我们这一次用new来写
function Person(name, age){
this.age = age
this.name = name
}
Person.prototype = {
say: function(){
console.log('say')
},
jump: function(){
console.log('jump')
}
}
var persons = []
for(var i=0; i<100; i++){
persons.push(new Person(name, age))
}
我们可以从3中的代码看到4中代码,发现其实new本质上是JS之父发明给我们的语法糖,帮我们少些一些代码(一般new都是和构造函数在一起的,后面的函数一般用首字母大写用来区分和其他的普通函数的区别)
5、 constructor属性
new 操作为了记录「临时对象是由哪个函数创建的」,会预先在person.prototype加一个constructor 属性,
person.prototype = {
constructor: person
}
如果我们从新对person.prototype赋值就会覆盖掉constructor这个属性,所以我们应该这样写
person.prototype.say = function(){
console.log('say')
}
person.prototype.jump = function(){
console.log('jump')
}
哇,感觉自己现在对new的理解更透彻了,开心,耶
参考链接: https://zhuanlan.zhihu.com/p/23987456