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 相关文章推荐
让任务管理器中的CPU跳舞的js代码
Nov 01 Javascript
jquery模拟按下回车实现代码
Sep 20 Javascript
js或者jquery判断图片是否加载完成实现代码
Mar 20 Javascript
单击浏览器右上角的X关闭窗口弹出提示的小例子
Jun 12 Javascript
JS实现很酷的EMAIL地址添加功能实例
Feb 28 Javascript
基于javascript实现样式清新图片轮播特效
Mar 30 Javascript
半个小时学json(json传递示例)
Dec 25 Javascript
AngularJS双向数据绑定原理之$watch、$apply和$digest的应用
Jan 30 Javascript
vue.js element-ui tree树形控件改iview的方法
Mar 29 Javascript
pageGroup.js实现分页功能
Jul 27 Javascript
JS获取当前时间戳方法解析
Aug 29 Javascript
JS highcharts实现动态曲线代码示例
Oct 16 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安全性问题中的:Null 字符问题
2013/06/21 PHP
PHP函数实现从一个文本字符串中提取关键字的方法
2015/07/01 PHP
js获取图片长和宽度的代码
2009/11/24 Javascript
artdialog的图片/标题以及关闭按钮不显示的解决方法
2013/06/27 Javascript
简介JavaScript中strike()方法的使用
2015/06/08 Javascript
js滑动提示效果代码分享
2016/03/10 Javascript
ES6新特性之数组、Math和扩展操作符用法示例
2017/04/01 Javascript
react-intl实现React国际化多语言的方法
2020/09/27 Javascript
vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例
2020/11/20 Vue.js
[01:33]一分钟玩转DOTA2第三弹:DOTA2&DotA快捷操作大对比
2014/06/04 DOTA
点球小游戏python脚本
2018/05/22 Python
python学生信息管理系统(完整版)
2020/04/05 Python
win8.1安装Python 2.7版环境图文详解
2019/07/01 Python
python切片的步进、添加、连接简单操作示例
2019/07/11 Python
python实现滑雪游戏
2020/02/22 Python
基于Python的自媒体小助手---登录页面的实现代码
2020/06/29 Python
基于logstash实现日志文件同步elasticsearch
2020/08/06 Python
python用tkinter实现一个简易能进行随机点名的界面
2020/09/27 Python
利用Python如何画一颗心、小人发射爱心
2021/02/21 Python
Python 调用C++封装的进一步探索交流
2021/03/04 Python
如何使用localstorage代替cookie实现跨域共享数据问题
2018/04/18 HTML / CSS
html5的新玩法——语音搜索
2013/01/03 HTML / CSS
HTML中fieldset标签概述及使用方法
2013/02/01 HTML / CSS
马来西亚最热门的在线时尚商店:FashionValet
2018/11/11 全球购物
美体小铺奥地利官方网站:The Body Shop奥地利
2019/04/11 全球购物
若干个Java基础面试题
2015/05/19 面试题
旅游管理实习自我鉴定
2013/09/29 职场文书
讲文明树新风公益广告宣传方案
2014/02/25 职场文书
协议书的格式
2014/04/23 职场文书
公司年会策划方案
2014/05/17 职场文书
安全生产承诺书范文
2014/05/22 职场文书
公司开业庆典策划方案
2014/06/04 职场文书
小孩不笨观后感
2015/06/03 职场文书
古诗文之爱国名句(77句)
2019/09/24 职场文书
如何用六步教会你使用python爬虫爬取数据
2022/04/06 Python
win10滚动条自动往上跑怎么办?win10滚动条自动往上跑的解决方法
2022/08/05 数码科技