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 相关文章推荐
jQuery lazyload 的重复加载错误以及修复方法
Nov 19 Javascript
php析构函数的具体用法小结
Mar 11 Javascript
jquery获取form表单input元素值的简单实例
May 30 Javascript
JS实现title标题栏文字不间断滚动显示效果
Sep 07 Javascript
基于BootstrapValidator的Form表单验证(24)
Dec 12 Javascript
用jQuery实现优酷首页轮播图
Jan 09 Javascript
Bootstrap Table使用整理(一)
Jun 09 Javascript
微信小程序 获取二维码实例详解
Jun 23 Javascript
浅谈vue-router 路由传参的方法
Dec 27 Javascript
vue3.0 CLI - 2.2 - 组件 home.vue 的初步改造
Sep 14 Javascript
微信小程序获取复选框全选反选选中的值(实例代码)
Dec 17 Javascript
小程序如何写动态标签的实现方法
Feb 05 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
探讨多键值cookie(php中cookie存取数组)的详解
2013/06/06 PHP
php中chdir()函数用法实例
2014/11/13 PHP
PHP+MySQL之Insert Into数据插入用法分析
2015/09/27 PHP
基于Laravel5.4实现多字段登录功能方法示例
2017/08/11 PHP
Laravel中批量赋值Mass-Assignment的真正含义详解
2017/09/29 PHP
JavaScript中split() 使用方法汇总
2015/04/17 Javascript
js操作css属性实现div层展开关闭效果的方法
2015/05/11 Javascript
jQuery实现tab选项卡效果的方法
2015/07/08 Javascript
贴近用户体验的Jquery日期、时间选择插件
2015/08/19 Javascript
jQuery unbind 删除绑定事件详解
2016/05/24 Javascript
Bootstrap零基础学习第一课之模板
2016/07/18 Javascript
Javascript中字符串replace方法的第二个参数探究
2016/12/05 Javascript
Bootstrap源码解读网格系统(3)
2016/12/22 Javascript
jquery获取transform里的值实现方法
2017/12/12 jQuery
vue单页面应用打开新窗口显示跳转页面的实例
2018/09/21 Javascript
Angular2实现的秒表及改良版示例
2019/05/10 Javascript
详解小程序云开发数据库
2019/05/20 Javascript
Vue.js中的组件系统
2019/05/30 Javascript
一文快速了解JQuery中的AJAX
2019/05/31 jQuery
[01:11:28]DOTA2-DPC中国联赛定级赛 RNG vs Phoenix BO3第一场 1月8日
2021/03/11 DOTA
Python MD5文件生成码
2009/01/12 Python
python访问sqlserver示例
2014/02/10 Python
python爬虫教程之爬取百度贴吧并下载的示例
2014/03/07 Python
python简单猜数游戏实例
2015/07/09 Python
用生成器来改写直接返回列表的函数方法
2017/05/25 Python
解决pycharm py文件运行后停止按钮变成了灰色的问题
2018/11/29 Python
Python time库基本使用方法分析
2019/12/13 Python
Pyecharts绘制全球流向图的示例代码
2020/01/08 Python
CSS3 中filter(滤镜)属性使用详解
2020/04/07 HTML / CSS
Urban Outfitters英国官网:美国平价服饰品牌
2016/11/25 全球购物
Gweniss格温妮丝女包官网:英国纯手工制造潮流包包品牌
2018/02/07 全球购物
Desigual英国官网:在线购买原创服装
2018/03/09 全球购物
群众路线问题查摆对照检查材料
2014/10/04 职场文书
单位婚育证明范本
2014/11/21 职场文书
推荐六本经典文学奖书籍:此生必读
2019/08/22 职场文书
Python Matplotlib库实现画局部图
2021/11/17 Python