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 相关文章推荐
JQuery 国际象棋棋盘 实现代码
Jun 26 Javascript
图片轮换效果实现代码(点击按钮停止执行)
Apr 12 Javascript
Extjs优化(二)Form表单提交通用实现
Apr 15 Javascript
JS 获取浏览器和屏幕宽高等信息代码
Mar 31 Javascript
js实现使用鼠标拖拽切换图片的方法
May 04 Javascript
浅谈下拉菜单中的Option对象
May 10 Javascript
JavaScript中用sort()方法对数组元素进行排序的操作
Jun 09 Javascript
js for循环倒序输出数组元素的实例
Mar 01 Javascript
Vue-Router模式和钩子的用法
Feb 28 Javascript
Vue实现textarea固定输入行数与添加下划线样式的思路详解
Jun 28 Javascript
vue搜索和vue模糊搜索代码实例
May 07 Javascript
支付宝小程序实现省市区三级联动
Jun 21 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
PHP+javascript液晶时钟
2006/10/09 PHP
php使用类继承解决代码重复的问题
2015/02/11 PHP
JavaScript setTimeout和setInterval的使用方法 说明
2010/03/25 Javascript
ExtJS 下拉多选框lovcombo
2010/05/19 Javascript
用函数模板,写一个简单高效的 JSON 查询器的方法介绍
2013/04/17 Javascript
js控制web打印(局部打印)方法整理
2013/05/29 Javascript
jQuery Ajax()方法使用指南
2014/11/19 Javascript
node.js中的fs.readSync方法使用说明
2014/12/17 Javascript
jQuery easyui的validatebox校验规则扩展及easyui校验框validatebox用法
2016/01/18 Javascript
Vue.js之slot深度复制详解
2017/03/10 Javascript
如何在 Vue.js 中使用第三方js库
2017/04/25 Javascript
移动端效果之IndexList详解
2017/10/20 Javascript
vue如何通过id从列表页跳转到对应的详情页
2018/05/01 Javascript
微信小程序排坑指南详解
2018/05/23 Javascript
Nodejs使用Mongodb存储与提供后端CRD服务详解
2018/09/04 NodeJs
Vuex 单状态库与多模块状态库详解
2018/12/11 Javascript
浅谈vue后台管理系统权限控制思考与实践
2018/12/19 Javascript
详解小程序循环require之坑
2019/03/08 Javascript
JS禁用右键、禁用Ctrl+u、禁用Ctrl+s、禁用F12的实现代码
2020/12/01 Javascript
[05:06]DOTA2-DPC中国联赛 正赛 VG vs Magma选手采访
2021/03/11 DOTA
布同 Python中文问题解决方法(总结了多位前人经验,初学者必看)
2011/03/13 Python
Python中字典(dict)和列表(list)的排序方法实例
2014/06/16 Python
python将文本转换成图片输出的方法
2015/04/28 Python
基于Python中单例模式的几种实现方式及优化详解
2018/01/09 Python
python3+PyQt5使用数据库表视图
2018/04/24 Python
Python2和Python3中urllib库中urlencode的使用注意事项
2018/11/26 Python
python 实现的发送邮件模板【普通邮件、带附件、带图片邮件】
2019/07/06 Python
Django Docker容器化部署之Django-Docker本地部署
2019/10/09 Python
英国航空官网:British Airways
2016/09/11 全球购物
纽约市的奢华内衣目的地:Anya Lust
2019/08/02 全球购物
2014年医院十一国庆节活动方案
2014/09/15 职场文书
收款授权委托书
2014/10/02 职场文书
2017年寒假少先队活动总结
2016/04/06 职场文书
工作一年自我鉴定
2019/06/20 职场文书
使用Djongo模块在Django中使用MongoDB数据库
2021/06/20 Python
Django+Nginx+uWSGI 定时任务的实现方法
2022/01/22 Python