构造函数
JS可以基于构造函数创建实例对象,我们可以用一个简单的函数来举例:
function Person(){
this.sex = 'male';
this.Name = 'rober';
this.Run = function(){console.log(this.Name + 'is running');}
}
let person = new Person();
person.Run() // rober is running
在上文中的Person只是一个函数,里边并没有return 任何东西,但当我们用new 调用构造函数后,便生成了一个person的实例对象。其实JS的new在背后讲要实例化的方法做了一些调整,如下:
function Person() {
this = {};
this.sex = 'male';
this.Name = 'rober';
this.Run = function() {console.log(this.Name + 'is running');}
return this;
}
new 关键字自动在函数里讲this初始化,并在最后返回了。这就是为什么我们new一个方法可以有对象可以返回。如果只是“let person = Person()”。那么person便是undefined了。
但Person终究还是一个方法,虽然我们可以让它实例化,但是很容易让人混淆,尤其是用惯JAVA或C#等语言的的人,还是会觉得class更加亲切一点。所以JS也引进了class。但只是为了让用户不会混淆OOP语言的概念,但实质上是一样的。我们就把上边的Person改成class:
class Person{
sex = 'male'
constructor(){
this.name = 'rober';
}
Run(){
console.log(this.name + 'is running');
}
}
let person = new Person();
person.Run();
当我们用new关键字去实例化class对象时,其实是跟实例化函数是一样的,只不过class 是在constructor方法里去初始化this,并返回。
值得注意的是,class Person的Run方法实例化还是有些特别,跟 function Person 的 Run方法有区别。这就需要了解JS中原型的概念了。
原型 Prototype
原型的概念对于JS来说非常重要,可以说JS是以原型为基础的语言。在JS里,所有的对象都有Prototype属性,这也是JS继承方法的方式。
person.toString();
当我们调用toString方法时,即使Person并未定义此方法,但JS还是执行并未报错。这是因为JS在Person中未找到toString方法后,便会去其原型里去查找,因为JS所有对象都有原型,所以JS会一层一层的往上找,先是Person的原型,再是Person原型的原型,直到查到Object的原型便到头了,如果还未找到此方法才会报错,toString方法就在Object的原型里,所以并未报错可以正确执行。JS在一层一层的顺着像链一样的原型往上查找,这个链我们称之为原型链。
现在我们回到之前的问题,用class Person 实例化的对象里的方法是存放在原型里,而不是属于自己的方法。
如上图,用class Person 初始化后,Run方法是在原型里的。
而用function Person 初始化后,Run方法则直接存放在了new 出来的对象里了。
虽然功能是一样的,但是放在原型里就意味着每次初始化新的对象并不需要创建新的Run方法,用Person Class的方法就好,而Person function每次new新的对象都要创建新的Run方法。如果new的对象比较少也不会有什么区别,但想象一下,如果一个大项目,需要new上千个对象,自然用class可以节省更多内存。
版权归原作者 go_with_dream 所有, 如有侵权,请联系我们删除。