JavaScript 面向对象(五)构造函数

五、构造函数

至今,我们已经学习了非常多的调用函数的方式:

  1. 圆括号直接调用
  2. 对象打点调用
  3. 定时器调用
  4. 事件处理函数调用
  5. 数组枚举调用

它们体现的不同点就是函数上下文不用,它们里面的this不一样!

现在,我们要学习新的函数调用方法!就是用 new 运算符来调用函数!


5.1 new 运算符

我们现在试着用new运算符调用一个函数:


此时函数可以执行,弹出 你好。也就是说new 是一个全新的调用函数的方式,我们关心的是这个函数的上下文是谁?



用new运算符调用一个函数的时候,会经历四步走:

  1. 函数内部悄悄的创建一个局部变量,是一个空对象{}。

  2. 函数将自己的上下文设置为这个空对象{},即所有语句中的this就表示这个空对象。

  3. 函数将执行所有语句。

  4. 所有语句执行后,函数将return这个对象,函数将把自己的上下文返回。


所以,遇见new操作符,马上想起四步走!


目前为止,我们发现,哟!这个new运算符能够调用函数,还能返回一个对象!




我们发现用new 操作符,可以返回具有相同属性群的对象:




我们说,可以认为 People 是一个“类(class)”,xiaoming , xiaohong , xiaoqing 都是这个类的“实例(instance)”

JS中没有类的概念,我们这里只是和 Java、C++、C# 做一个类比,JS中只有构造函数,当一个函数被new操作符调用的时候,这个函数就是一个构造函数,它总能返回一类的具有相同属性群的对象,感觉在“构造东西”。所以这个函数很神奇,像一个模子,在制作类似的对象。

为了提醒其他程序猿,这是一个必须用new调用的函数,换句话说提醒别人这是一个构造函数,这类函数的名字必须首字母大写。



我们看不用new 操作符调用构造函数会发生什么:


由于我们直接调用了构造函数,此时就是标准的函数直接加圆括号调用,函数里面的 this 是 window 对象,所以,此时 name 、age 、sex 都被设置为了 window 对象的属性,我们知道 window  对象的属性是全局变量,此时能够弹出12。


下面就是一个标准的构造函数:




给学过其他语言的同学提个醒,JS中没有Class关键字(ECMAScript2016 增加了Class关键字),我们就是使用new操作符的时候,会按‘四步走’创建一些些具有相同属性群的实例,此时就感觉有了‘类’,JS只提“构造函数”,而不提“类”。


复习,学习了什么:

  • 一个函数可以用 new 来调用,此时这个函数将按四步走执行,此时将返回一个对象,这个函数我们称为构造函数。
  • 一般的,用 new 来多次调用同一个函数,总能得到具有相同属性群的对象,我们可以称这些对象是“同一个类的实例”,或者称为“同一类的对象”。
  • new 就是一个运行函数的运算符,不要太有 “类” 的概念!会害了你!

JS不是一个面向对象(OO)的语言,它只是基于对象(BO)。


小题目:


这个函数是不是一个构造函数? 答案:不知道。因为只要用new 操作符调用一个函数,此时这个函数就是一个构造函数,至于函数名字没有大写,只是我们的习惯,不是语言要求。


再来,这个函数是不是构造函数:


答案也是不确定!因为用new调用它就是一个构造函数,不用new调用就不是,比如我们直接调用:


函数根本没有返回值!此时obj就是null 。


所以,构造函数真的没有什么!就是一个全新的函数调用方式!

构造函数和普通函数没有什么区别,只不过这家伙能够被new来调用,事实上所有函数都能用new调用!


5.2 原型链

每一个构造函数都有一个属性叫做prototype,指向一个对象,当这个构造函数被new 的时候,它的每一个实例的__proto__属性,也指向这个对象


每个函数天生都有prototype属性,指向一个空对象,也就是说,我们不需要定义这个prototype属性,任何一个函数只要写出来,它就拥有了prototype属性,这个属性对它自己而言没有任何意义!它的唯一意义是儿子们的指明灯!构造函数的 prototype属性 指向谁,它new出来的儿子的__proto__属性就指向谁!





我们称 People.prototype 是People构造函数的 “原型”,People.prototype 是小明的 “原型对象”。


__proto__是神器,有原型链查找功能,当xiaoming身上没有某个属性的时候,系统会沿着__proto__去寻找它的运行对象身上有没有这个属性。






一定要记住这个三角恋:构造函数的 prototype 指向谁,new 出来的玩意儿的__proto__就指向谁!!!这个__proto__有原型链查找功能!


小题目:


小明身上虽然没有random属性,但是小明的__proto__身上有这个属性,所以小明能够打点调用random属性。


一定记住,任何函数都有prototype属性,prototype是一个空对象,而不是函数的东西,一定没有prototype属性,prototype属性的值是一个对象,这个函数new出来的东西__proto__指向这个对象。



5.3 在原型上定义方法


我们刚才知道如果把函数写在构造函数里面,就相当于定义在了对象上,此时函数会产生多个不用的副本,影响程序效率,此时可以把函数定义在构造函数的原型上,这样所有new出的东西, __proto__就会指向这个对象,从而能够使用这个方法。





5.4 构造函数和实例的关系

构造函数:抽象,定义的是一类对象应该具有什么属性,什么方法, 描述规则,描述蓝图。

实例:具体,根据规则、蓝图创建的一个个具体的实例,它能拥有属性,并且能调用方法。



等价于:



再看下面的小例子:


构造函数中,我们用prototype来定义方法,定义的是构造函数的实例的方法,不是构造函数的方法。







  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值