JavaScript方法_动力节点Java学院整理


Posted in Javascript onJune 28, 2017

在一个对象中绑定函数,称为这个对象的方法。

在JavaScript中,对象的定义是这样的:

var xiaoming = {
 name: '小明',
 birth: 1990
};

但是,如果我们给xiaoming绑定一个函数,就可以做更多的事情。比如,写个age()方法,返回xiaoming的年龄:

var xiaoming = {
 name: '小明',
 birth: 1990,
 age: function () {
  var y = new Date().getFullYear();
  return y - this.birth;
 }
};

xiaoming.age; // function xiaoming.age()
xiaoming.age(); // 今年调用是25,明年调用就变成26了

绑定到对象上的函数称为方法,和普通函数也没啥区别,但是它在内部使用了一个this关键字,这个东东是什么?

在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以, this.birth可以拿到xiaomingbirth属性。

让我们拆开写:

function getAge() {
 var y = new Date().getFullYear();
 return y - this.birth;
}

var xiaoming = {
 name: '小明',
 birth: 1990,
 age: getAge
};

xiaoming.age(); // 25, 正常结果
getAge(); // NaN

单独调用函数getAge()怎么返回了NaN?请注意,我们已经进入到了JavaScript的一个大坑里。

JavaScript的函数内部如果调用了this,那么这个this到底指向谁?

答案是,视情况而定!

如果以对象的方法形式调用,比如xiaoming.age(),该函数的this指向被调用的对象,也就是xiaoming,这是符合我们预期的。

如果单独调用函数,比如getAge() ,此时,该函数的this指向全局对象,也就是window

坑爹啊!

更坑爹的是,如果这么写:

var fn = xiaoming.age; // 先拿到xiaoming的age函数
fn(); // NaN

也是不行的!要保证this指向正确,必须用obj.xxx()的形式调用!

由于这是一个巨大的设计错误,要想纠正可没那么简单。ECMA决定,在strict模式下让函数的this指向undefined,因此,在strict模式下,你会得到一个错误:

'use strict';

var xiaoming = {
 name: '小明',
 birth: 1990,
 age: function () {
  var y = new Date().getFullYear();
  return y - this.birth;
 }
};

var fn = xiaoming.age;
fn(); // Uncaught TypeError: Cannot read property 'birth' of undefined

这个决定只是让错误及时暴露出来,并没有解决this应该指向的正确位置。

有些时候,喜欢重构的你把方法重构了一下:

'use strict';

var xiaoming = {
 name: '小明',
 birth: 1990,
 age: function () {
  function getAgeFromBirth() {
   var y = new Date().getFullYear();
   return y - this.birth;
  }
  return getAgeFromBirth();
 }
};

xiaoming.age(); // Uncaught TypeError: Cannot read property 'birth' of undefined

结果又报错了!原因是this指针只在age方法的函数内指向xiaoming,在函数内部定义的函数,this又指向undefined了!(在非strict模式下,它重新指向全局对象window!)

修复的办法也不是没有,我们用一个that变量首先捕获this

'use strict';

var xiaoming = {
 name: '小明',
 birth: 1990,
 age: function () {
  var that = this; // 在方法内部一开始就捕获this
  function getAgeFromBirth() {
   var y = new Date().getFullYear();
   return y - that.birth; // 用that而不是this
  }
  return getAgeFromBirth();
 }
};

xiaoming.age(); // 25

var that = this;,你就可以放心地在方法内部定义其他函数,而不是把所有语句都堆到一个方法中。

apply

虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefinedwindow,不过,我们还是可以控制this的指向的!

要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。

apply修复getAge()调用:

function getAge() {
 var y = new Date().getFullYear();
 return y - this.birth;
}

var xiaoming = {
 name: '小明',
 birth: 1990,
 age: getAge
};

xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空

另一个与apply()类似的方法是call() ,唯一区别是:

  1. apply()把参数打包成Array再传入;
  2. call()把参数按顺序传入。

比如调用Math.max(3, 5, 4),分别用apply()和call()实现如下:

Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5

对普通函数调用,我们通常把this绑定为null。

装饰器

利用apply() ,我们还可以动态改变函数的行为。

JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数。

现在假定我们想统计一下代码一共调用了多少次parseInt() ,可以把所有的调用都找出来,然后手动加上count += 1,不过这样做太傻了。最佳方案是用我们自己的函数替换掉默认的parseInt():

var count = 0;
var oldParseInt = parseInt; // 保存原函数

window.parseInt = function () {
 count += 1;
 return oldParseInt.apply(null, arguments); // 调用原函数
};

// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
count; // 3

Javascript 相关文章推荐
8款非常棒的响应式jQuery 幻灯片插件推荐
Feb 02 Javascript
javascript jscroll模拟html元素滚动条
Dec 18 Javascript
JS限制上传图片大小不使用控件在本地实现
Dec 19 Javascript
Jquery实现带动画效果的经典二级导航菜单
Mar 22 Javascript
jquery的attr方法禁用表单元素禁用输入内容
Jun 23 Javascript
jquery仅用6行代码实现滑动门效果
Sep 07 Javascript
angularJS与bootstrap结合实现动态加载弹出提示内容
Oct 16 Javascript
详解Matlab中 sort 函数用法
Mar 20 Javascript
Chrome浏览器的alert弹窗禁止再次弹出后恢复的方法
Dec 30 Javascript
Angularjs自定义指令实现三级联动 选择地理位置
Feb 13 Javascript
vue组件之间通信方式实例总结【8种方式】
Feb 22 Javascript
浅谈Vue3.0新版API之composition-api入坑指南
Apr 30 Javascript
微信小程序后台解密用户数据实例详解
Jun 28 #Javascript
JavaScript箭头函数_动力节点Java学院整理
Jun 28 #Javascript
JavaScript之filter_动力节点Java学院整理
Jun 28 #Javascript
JavaScript高阶函数_动力节点Java学院整理
Jun 28 #Javascript
JavaScript之Date_动力节点Java学院整理
Jun 28 #Javascript
ES6深入理解之“let”能替代”var“吗?
Jun 28 #Javascript
jQuery、layer实现弹出层的打开、关闭功能
Jun 28 #jQuery
You might like
php程序的国际化实现方法(利用gettext)
2011/08/14 PHP
利用PHP实现短域名互转
2013/07/05 PHP
php强制文件下载而非在浏览器打开的自定义函数分享
2014/05/08 PHP
PHP与MYSQL中UTF8编码的中文排序实例
2014/10/21 PHP
jQuery制作仿腾讯web qq用户体验桌面
2013/08/20 Javascript
客户端js判断文件类型和文件大小即限制上传大小
2013/11/20 Javascript
jquery Ajax 实现加载数据前动画效果的示例代码
2014/02/07 Javascript
js弹出确认是否删除对话框
2014/03/27 Javascript
node.js中的fs.chmod方法使用说明
2014/12/18 Javascript
javascript自定义右键弹出菜单实现方法
2015/05/25 Javascript
JavaScript简单实现弹出拖拽窗口(二)
2016/06/17 Javascript
p5.js 毕达哥拉斯树的实现代码
2018/03/23 Javascript
element-ui循环显示radio控件信息的方法
2018/08/24 Javascript
微信小程序实现bindtap等事件传参
2019/04/08 Javascript
js设计模式之单例模式原理与用法详解
2019/08/15 Javascript
Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作
2020/08/31 Javascript
[04:52]2015国际邀请赛LGD战队晋级之路
2015/08/14 DOTA
[39:00]Optic vs VP 2018国际邀请赛淘汰赛BO3 第三场 8.24
2018/08/25 DOTA
python使用calendar输出指定年份全年日历的方法
2015/04/04 Python
win10下Python3.6安装、配置以及pip安装包教程
2017/10/01 Python
Python3爬楼梯算法示例
2019/03/04 Python
python 杀死自身进程的实现方法
2019/07/01 Python
详解基于python的多张不同宽高图片拼接成大图
2019/09/26 Python
Python+appium框架原生代码实现App自动化测试详解
2020/03/06 Python
详解pandas.DataFrame.plot() 画图函数
2020/06/14 Python
Pytorch框架实现mnist手写库识别(与tensorflow对比)
2020/07/20 Python
Python WebSocket长连接心跳与短连接的示例
2020/11/24 Python
PyQt5中QSpinBox计数器的实现
2021/01/18 Python
英国性感内衣和睡衣品牌:Bluebella
2018/01/26 全球购物
美国最大的在线寄售和旧货店:Swap.com
2018/08/27 全球购物
OSPF有什么优点?为什么OSPF比RIP收敛快?
2013/02/13 面试题
大专生简历的自我评价
2013/11/26 职场文书
小学生美德少年事迹
2014/02/02 职场文书
人事部岗位职责范本
2014/03/05 职场文书
MYSQL优化之数据表碎片整理详解
2022/04/03 MySQL
golang生成并解析JSON
2022/04/14 Golang