this的含义
this 本身原本很简单,总是指向类的当前实例。因此编写的 JS 采用函数式写法,而不是面向对象式,你所有的代码里 this 会少很多,甚至没有。所以应用场景就是用 this 时,应该是在使用对象/类 方式开发,否则 this 只是函数调用时的副作用。
this的约定
- 在 function 内部被创建
- 指向调用时所在函数所绑定的对象
- this 不能被赋值,但可以被 call/apply 改变
this的常见应用场景
this 和构造器
this 本身就是类定义时构造器里需要用到的,按照 JavaScript 的习惯写法, this 应该挂属性/字段,方法都应该放在原型上。
function Tab(nav, content) {
this.nav = nav
this.content = content
}
Tab.prototype.getNav = function() {
return this.nav;
};
this 和对象
JS 中的对象不用类也可以创建,当我们用 OOP 方式写 JS 代码,可避免的会用到 this,方法内会访问类的内部属性(字段),也可能会调用类的另一个方法。
var tab = {
nav: '',
content: '',
getNav: function() {
return this.nav;
},
setNav: function(n) {
this.nav = n;
}
}
当类的方法内又有一个 function 时,比如浏览器端开发经常遇见的给 DOM 元素添加事件,这时如果事件处理器(handler)中的想调用类的一个方法,此时 handler 内的 this 是 dom 元素而非类的当前对象。这个时候,需要把 this 暂存,开发者发挥着自己的聪明才智留下了几种经典的命名 me, self, that, _this。
function listenEvents(){
$(".my_foot_today ul li").on("mouseover ",function(){
$(this).find('.foot_chacha').stop().fadeIn(100);
}).on("mouseout",function(){
$(this).find('.foot_chacha').stop().fadeOut(100);
})
$(".del_today a").on("click",function(){
var _this_ = $(this);
ConfirmBox.confirm("", "确认删除当天的浏览记录吗?", function(){
var date = _this_.data("date");
var goodsList = [];
$(".my_foot_today[data-date='" + date + "'] li").each(function(){
goodsList.push(parseInt($(this).data("goodsid")));
});
delHistory(goodsList,date);
return true;
},function(){
return true;
})
})
}
this 和函数
this 和独立的函数放在一起是没有意义的。
function showMsg() {
alert(this.message)
}
showMsg() // undefined
定义 showMsg,然后以函数方式调用(函数所绑定的对象就是window),因此这里的this是window对象,this.message 是 undefined。因此坚决杜绝在 纯函数内使用 this,但有时候会这么写,调用方式使用 call/apply。
function showMsg() {
alert(this.message)
}
var m1 = {
message: '输入的电话号码不正确'
}
var m2 = {
message: '输入的身份证号不正确'
}
showMsg.call(m1) // '输入的电话号码不正确'
showMsg.call(m2) // '输入的身份证号不正确'
用这种方式可以节省一些代码量,比如当两个 类/对象 有一共相似的方法时,不必写两份,只要定义一个,然后将其绑定在各自的原型和对象(作为this参数绑定进来)上。这时候其实你还是在函数里面使用对象或类(),只是间接使用罢了。关于call/apply用法查看另外我的另外一篇。
全局环境的 this
this 是 “指向调用时所在函数所绑定的对象”,这句话没毛病,有时候我们也会在全局环境中使用(很少使用),全局环境中有不同的宿主对象,浏览器环境中是 window, node 环境中是 global。
浏览器环境中非函数内 this 指向 window。
alert(window=== this) // true
因此你会看很很多开源 JS lib 这么写,比如jQuery,requirejs,:
(function() {
// ...
})(this);
(function() {
// ...
}).call(this);
(function() {
// ...
})(window);
把全局变量 window 传入匿名函数。
this 和 DOM/事件
this指向div,button等DOM对象
<!-- this 指向 div -->
<div onclick="alert(this)"></div>
$('#nav').on('click', function() {
alert(this) // 指向 nav
})
this和call/apply
call/apply 是函数调用的另外两种方式,两者的第一个参数都可以改变函数的上下文 this。具体参照上面的。
call/apply 在 JS 里体现动态语言特性及动态语言的流行原因,其在 JS 用途如此广泛。ES5发布时将其采纳,提了一个更高级的方法 bind。
var modal = {
message: 'This is A'
}
function showMsg() {
alert(this.message)
}
var otherShowMsg = showMsg.bind(modal)
otherShowMsg()
ES6 箭头函数(arrow function) 和 this
判断 this 指向谁,看执行时而非定义时,只要函数(function)没有绑定在对象上调用,它的 this 就是 window。 ,前面一直用这句话来判断 this 的指向,在箭头函数里前面半句就失效了,箭头函数的特征就是,定义在哪,this 就指向那。即箭头函数定义在一个对象里,那箭头函数里的 this 就指向该对象。
var book = {
author: 'John Resig',
init: function() {
document.onclick = ev => {
alert(this.author) ; // 这里的 this 不是 document 了
}
}
};
book.init()
对象 book 里有一个属性 author, 有一个 init 方法, 给 document 添加了一个点击事件,如果是传统的函数,我们知道 this 指向应该是 document,但箭头函数会指向当前对象 book。
总结
this 本质是和面向对象联系的,和写类,对象关联一起的, 和“函数式”没有关系的。如果你采用过程式函数式开发,完全不会用到一个 this。
网友评论