JavaScript中的普通函数与构造函数比较


Posted in Javascript onApril 07, 2015

问题

什么是构造函数?
构造函数与普通函数区别是什么?
用new关键字的时候到底做了什么?
构造函数有返回值怎么办?
构造函数能当普通函数调用吗?

以下是我的一些理解,理解错误的地方恳请大家帮忙指正,谢谢!

this
this永远指向当前正在被执行的函数或方法的owner。例如:

function test(){
  console.log(this);
}
test();
//Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}

上面这段代码中,我们在页面中定义了一个test()函数,然后在页面中调用。函数定义在全局时,其owner就是当前页面,也就是window对象。

this指向的几种情况

1.全局中调用

    this.name //this指向window对象
   
2.函数调用

    test();//test()函数中的this也指向window对象
   
3.对象的方法调用

    obj1.fn();//obj1对象的fn()方法中的this指向obj1
   
4.调用构造函数
    var dog=new Dog();//构造函数内的this指向新创建的实例对象,也就是这里的dogcall和apply

call和apply的作用一样,只是接受参数的方式不一样,call接受的是多个单个参数,apply接受的是参数数组。
call和apply的作用简单地可以说成,当一个对象实例缺少一个函数/方法时,可以调用其他对象的现成函数/方法,其方式是通过替换其中的this为这个对象实例,改变函数运行时的上下文。
例如:

function Dog(){
  this.sound="汪汪汪";
}
Dog.prototype.bark=function(){
  alert(this.sound);
}

现在我有另外一个cat对象:

var cat={sound:'喵喵喵'}

我也想让这个cat对象可以调用bark方法,这时候就不用重新为它定义bark方法了,可以用call/apply调用Dog类的bark方法:

Dog.prototype.bark.call(cat);

或者:

dog.bark.call(cat);

加点东西,变成一个带参数的栗子:

function Dog(){
  this.sound="汪汪汪";
}
Dog.prototype.bark=function(words){
  alert(this.sound+" "+words);
}
var dog=new Dog();
dog.bark("有小偷");//alert:汪汪汪  有小偷
Dog.prototype.bark.call(cat,"饿了");//alert:喵喵喵  饿了

普通函数
这是一个简单的普通函数:

function fn(){
  alert("hello sheila");
}
fn();//alert:hello sheila

普通函数与构造函数相比有四个明显特点:

1.不需要用new关键字调用

    fn();2.可以用return语句返回值

function fn(a,b){
    return a+b;
  }
  alert(fn(2,3));//alert:5

3.函数内部不建议使用this关键字
我们说不建议使用,当然硬要用是可以的,只是要注意这时候发生了什么。如果在普通函数内部使用this关键字定义变量或函数,因为这时候this指向的是window全局对象,这样无意间就会为window添加了一些全局变量或函数。

function greeting(){
    this.name="sheila";
    alert("hello "+this.name);
  }
  greeting();//alert:hello sheila
  alert(window.name);//alert:sheila

4.函数命名以驼峰方式,首字母小写

构造函数
在JavaScript中,用new关键字来调用定义的构造函数。默认返回的是一个新对象,这个新对象具有构造函数定义的变量和函数/方法。

举个栗子:

function Prince(name,age){
  this.gender="male";
  this.kind=true;
  this.rich=true;
  this.name=name;
  this.age=age;
}
Prince.prototype.toFrog=function(){
  console.log("Prince "+this.name+" turned into a frog.");
}
var prince=new Prince("charming",25);
prince.toFrog();//Prince charming turned into a frog.
prince.kind;//true

与普通函数相比,构造函数有以下明显特点:

1.用new关键字调用

    var prince=new Prince("charming",25);

2.函数内部可以使用this关键字
在构造函数内部,this指向的是构造出的新对象。用this定义的变量或函数/方法,就是实例变量或实例函数/方法。需要用实例才能访问到,不能用类型名访问。

 prince.age;//25
    Prince.age;//undefined

3.默认不用return返回值
构造函数是不需要用return显式返回值的,默认会返回this,也就是新的实例对象。当然,也可以用return语句,返回值会根据return值的类型而有所不同,细节将在下文介绍。

4.函数命名建议首字母大写,与普通函数区分开。
不是命名规范中的,但是建议这么写。

使用new关键字实例化的时候发生了什么?
以上文中的Prince()函数举个栗子:

1.第一步,创建一个空对象。

var prince={}

2.第二步,将构造函数Prince()中的this指向新创建的对象prince。
3.第三步,将prince的_proto_属性指向Prince函数的prototype,创建对象和原型间关系
4.第四步,执行构造函数Prince()内的代码。

构造函数有return值怎么办?
构造函数里没有显式调用return时,默认是返回this对象,也就是新创建的实例对象。
当构造函数里调用return时,分两种情况:

1.return的是五种简单数据类型:String,Number,Boolean,Null,Undefined。
这种情况下,忽视return值,依然返回this对象。

2.return的是Object
这种情况下,不再返回this对象,而是返回return语句的返回值。

function Person(name){
    this.name=name;
    return {name:"cherry"}
  }
  var person=new Person("sheila");
  person.name;//cherry
  p;//Object {name: "cherry"}
Javascript 相关文章推荐
Add Formatted Text to a Word Document
Jun 15 Javascript
javascript 特殊字符串
Feb 25 Javascript
利用js实现选项卡的特别效果的实例
Mar 03 Javascript
Angular用来控制元素的展示与否的原生指令介绍
Jan 07 Javascript
浅谈javascript语法和定时函数
May 03 Javascript
Node.js与Sails ~项目结构与Mvc实现及日志机制
Oct 14 Javascript
javascript中tostring()和valueof()的用法及两者的区别
Nov 16 Javascript
javascript图片延迟加载实现方法及思路
Dec 31 Javascript
微信小程序 rpx 尺寸单位详细介绍
Oct 13 Javascript
JS获取短信验证码倒计时的实现代码
May 22 Javascript
three.js实现圆柱体
Dec 30 Javascript
浅谈webpack devtool里的7种SourceMap模式
Jan 14 Javascript
jQuery控制cookie过期时间的方法
Apr 07 #Javascript
JavaScript随机生成信用卡卡号的方法
Apr 07 #Javascript
JavaScript实现信用卡校验方法
Apr 07 #Javascript
jQuery控制网页打印指定区域的方法
Apr 07 #Javascript
JavaScript使用指针操作实现约瑟夫问题实例
Apr 07 #Javascript
jquery.form.js实现将form提交转为ajax方式提交的方法
Apr 07 #Javascript
JavaScript中字符串分割函数split用法实例
Apr 07 #Javascript
You might like
ThinkPHP写第一个模块应用
2012/02/20 PHP
thinkphp的CURD和查询方式介绍
2013/12/19 PHP
实现png图片和png背景透明(支持多浏览器)的方法
2009/09/08 Javascript
在js文件中写el表达式取不到值的原因及解决方法
2013/12/23 Javascript
vue指令以及dom操作详解
2017/03/04 Javascript
原生js编写2048小游戏
2017/03/17 Javascript
React实践之Tree组件的使用方法
2017/09/30 Javascript
vue配置多页面的实现方法
2018/05/22 Javascript
js+html5实现手机九宫格密码解锁功能
2018/07/30 Javascript
Vue.js中的extend绑定节点并显示的方法
2019/06/20 Javascript
ES6模板字符串和标签模板的应用实例分析
2019/06/25 Javascript
使用Easyui实现查询条件的后端传递并自动刷新表格的两种方法
2019/09/09 Javascript
TypeScript中使用getElementXXX()的示例代码
2019/09/12 Javascript
[02:11]DOTA2上海特级锦标赛主赛事第二日RECAP
2016/03/04 DOTA
Python正则表达式匹配HTML页面编码
2015/04/08 Python
Python中list初始化方法示例
2016/09/18 Python
python中logging库的使用总结
2017/10/18 Python
浅谈numpy数组的几种排序方式
2017/12/15 Python
python使用Matplotlib绘制分段函数
2018/09/25 Python
python中数组和矩阵乘法及使用总结(推荐)
2019/05/18 Python
基于Python实现船舶的MMSI的获取(推荐)
2019/10/21 Python
浅谈Python访问MySQL的正确姿势
2020/01/07 Python
Pytest如何使用skip跳过执行测试
2020/08/13 Python
从零开始的TensorFlow+VScode开发环境搭建的步骤(图文)
2020/08/31 Python
《狼和小羊》教学反思
2014/04/20 职场文书
新农村建设汇报材料
2014/08/15 职场文书
前台接待岗位职责
2015/02/03 职场文书
2015年财务人员个人工作总结
2015/07/27 职场文书
主婚人致辞精选
2015/07/28 职场文书
旷工检讨书大全
2015/08/15 职场文书
2016年党员学习廉政准则心得体会
2016/01/20 职场文书
某药房的新员工入职告知书!
2019/07/15 职场文书
golang协程池模拟实现群发邮件功能
2021/05/02 Golang
详细聊聊Oracle表碎片对性能有多大的影响
2022/03/19 Oracle
Kubernetes中Deployment的升级与回滚
2022/04/01 Servers
Windows server 2003卸载和安装IIS的图文教程
2022/07/15 Servers