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 相关文章推荐
js null,undefined,字符串小结
Aug 21 Javascript
jquery获取下拉列表的值为null的解决方法
Mar 18 Javascript
使用jQuery fancybox插件打造一个实用的数据传输模态弹出窗体
Jan 15 Javascript
Jquery实现网页跳转或用命令打开指定网页的解决方法
Jul 09 Javascript
在JavaScript中操作时间之getYear()方法的使用教程
Jun 11 Javascript
学习AngularJs:Directive指令用法(完整版)
Apr 26 Javascript
JS实现简单的天数计算器完整实例
Apr 28 Javascript
原生JS实现小小的音乐播放器
Oct 16 Javascript
详解webpack-dev-server使用方法
Sep 14 Javascript
详解Vue iview IE浏览器不兼容报错(Iview Bable polyfill)
Jan 07 Javascript
javascript实现异形滚动轮播
Nov 28 Javascript
js实现div色块拖动录制
Jan 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解答方法
2012/02/04 PHP
php在线解压ZIP文件的方法
2014/12/30 PHP
PHP list() 将数组中的值赋给变量的简单实例
2016/06/13 PHP
JavaScript实现删除电脑的关机键
2016/07/26 PHP
PHP使用观察者模式处理异常信息的方法详解
2019/09/24 PHP
一个不错的用JavaScript实现的UBB编码函数
2007/03/09 Javascript
理解Javascript_12_执行模型浅析
2010/10/18 Javascript
背景图跟随鼠标移动的Mootools插件实现代码
2011/12/12 Javascript
ExtJS DOM元素操作经验分享
2013/08/28 Javascript
Backbone.js中的集合详解
2015/01/14 Javascript
Node.js的Express框架使用上手指南
2016/03/12 Javascript
JS跨域交互(jQuery+php)之jsonp使用心得
2016/07/01 Javascript
Vue项目中quill-editor带样式编辑器的使用方法
2017/08/08 Javascript
node通过express搭建自己的服务器
2017/09/30 Javascript
仿京东快报向上滚动的实例
2017/12/13 Javascript
JS设计模式之状态模式概念与用法分析
2018/02/05 Javascript
微信小程序分享海报生成的实现方法
2018/12/10 Javascript
vue单页面在微信下只能分享落地页的解决方案
2019/04/15 Javascript
MySQLdb ImportError: libmysqlclient.so.18解决方法
2014/08/21 Python
python实现数独算法实例
2015/06/09 Python
Python判断两个对象相等的原理
2017/12/12 Python
使用tensorflow实现线性回归
2018/09/08 Python
python 对key为时间的dict排序方法
2018/10/17 Python
浅谈python下tiff图像的读取和保存方法
2018/12/04 Python
numpy中的ndarray方法和属性详解
2019/05/27 Python
python采集百度搜索结果带有特定URL的链接代码实例
2019/08/30 Python
Python时间差中seconds和total_seconds的区别详解
2019/12/26 Python
Python实现桌面翻译工具【新手必学】
2020/02/12 Python
python如何删除列为空的行
2020/07/17 Python
浅析Python 序列化与反序列化
2020/08/05 Python
美国Randolph太阳镜官网:美国制造的飞行员太阳镜和射击眼镜
2018/06/15 全球购物
人事档案接收函
2014/01/12 职场文书
金融专业毕业生自荐信
2014/06/26 职场文书
股东授权委托书
2014/10/15 职场文书
2015年“我们的节日·中秋节”活动总结
2015/07/30 职场文书
pytorch 运行一段时间后出现GPU OOM的问题
2021/06/02 Python