偶遇this之坑
前言
在写一个懒加载插件时,遇到一个坑,就是this的指向问题,我想这种情况大部分人都会遇到,就写下来,新手也有个参考。
事件
有些页面图片比较多,但用户还不一定会全看,这样的话,全部去加载这些图片,就有点浪费资源了,于是想写一个通用的插件来解决这个问题
想法
根据滚动条高度加屏幕高度来判断是否加载这张图片,需要懒加载的图片这样写
<img data-src="image/bg.jpg">
凡是加上这个属性的都会做懒加载处理。
this之坑
以下是最终的代码
function SetImg(top){
var imgs = Array.prototype.slice.apply(document.getElementsByTagName("img"));
this.imgs = imgs.filter(function(item,index){
return item.dataset.src;
});
this.top = top || 150;
}
SetImg.prototype = {
init:function(){
this.event();
},
setSrc:function(){
if(this.imgs.length===0){
window.removeEventListener("scroll",this.setSrc);
};
var _this = this;
this.imgs.forEach(function(item,index){
if(document.documentElement.clientHeight+document.body.scrollTop+_this.top>item.offsetTop||item.offsetTop<document.documentElement.clientHeight){
item.src = item.dataset.src;
_this.imgs.splice(index,1);
}
})
},
event:function(){
this.setSrc = this.setSrc.bind(this);
window.addEventListener("load",this.setSrc);
window.addEventListener("scroll",this.setSrc);
}
};
new SetImg().init();
这个代码已经解决了this的指向问题,也就是下面这句
this.setSrc = this.setSrc.bind(this);
一开始是没有这句话的,但问题是,我在setSrc里面使用了this,而恰恰那里面的this指向的是window,为什么指向window?因为这句话
window.addEventListener("load",this.setSrc);
window.addEventListener("scroll",this.setSrc);
我们说this始终指向一个对象,而现在给添加的事件,就是在window身上添加的,正如
element.addEventListener("click",fn);
这句不就是指向element吗,那上面的那个指向window,也就不足为奇了。因此这也是为什么最后我添加这么一句
this.setSrc = this.setSrc.bind(this);
其实一开始我没想要这么做,但这也是迫不得已的事,一开始我是这样写的:
window.addEventListener("load",this.setSrc.bind(this));
window.addEventListener("scroll",this.setSrc.bind(this));
但这样的问题是,bind返回的是一个新对象,而不是原本的this.setSrc。一般情况下,这也不是什么大问题,但坑就坑在this.setSrc里面的这句
if(this.imgs.length===0){
window.removeEventListener("scroll",this.setSrc);
};
看似一切都正常,但这是一个大坑,这里面的this.setSrc指向的是SetImg.setSrc,而
window.addEventListener("scroll",this.setSrc.bind(this));
this.setSrc.bind(this)这是一个新对象,因此你根本就无法remove掉这个新对象。所以最终才想出个迫不得已的方法就是让this.setSrc变成新的那个对象。
可能有些朋友,不太懂为什么要写这么一句:
if(this.imgs.length===0){
window.removeEventListener("scroll",this.setSrc);
};
这句话的作用是,如果所有图片都加载完毕了,这个滚动事件,就不需要了。当然如果你直接使用window.onscroll这种情势来写,或许这个问题可以很好的解决,但作为一个插件用addEventListener是迫不得已的,因为我不知道哪个页面使用了onscroll事件,如果我直接那样写,就会把其他人写的事件覆盖掉。
结语
这种情况出现的概率还是蛮高的,导致这种问题的出现就是,事件里面的this和构造函数里面的this,指向的是不同的对象,所以啊这就是坑点。
说到正题,这个插件还不能用T_T,再改改吧
偶遇this之坑的更多相关文章
- 偶遇vue-awesome-swiper的坑
最近用vue重构一个移动端的项目,碰到了不少坑,今天拿移动端最著名的轮播插件swiper为例来说,由于这个项目没用UI库,纯手写的样式,沿用老的插件,自然而然的选择了vue-awesome-swipe ...
- 彻底理解js中this的指向,不必硬背。
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- this指向详解及改变它的指向的方法
一.this指向详解(彻底理解js中this的指向,不必硬背) 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是 ...
- 详解lastindex,正则test()与全局匹配g偶遇,带来一会true一会false的坑
一.简单的需求与奇怪的问题 周一接到需求文档,产品分类页的输入框,需要加一个智能下拉提醒的功能,大概就是用户输入啥,找到符合输入字段的产品名,进行下拉推荐,同时将此字段标红,有点类似于百度搜索的智能提 ...
- 【转】Vue 脱坑记 - 查漏补缺(汇总下群里高频询问的xxx及给出不靠谱的解决方案)
前言 文章内容覆盖范围,芝麻绿豆的破问题都有,不止于vue; 给出的是方案,但不是手把手一字一句的给你说十万个为什么! 有三类人不适合此篇文章: “喜欢站在道德制高点的圣母婊” – 适合去教堂 “无理 ...
- Android,我待你入初恋啊,你就别坑我了!
最近做了好多东西,东忙忙,西茫茫,ms最后都空欢喜一场. 1.小黄图,说是小黄图,其实只是网上爬下来的写真阿自拍阿什么的,绝对没有反党反共淫秽内容.后来的后来,admob被google停用了,不开心. ...
- Vue 脱坑记
问题汇总 Q:安装超时(install timeout) 方案有这么些: cnpm : 国内对npm的镜像版本 /* cnpm website: https://npm.taobao.org/ */ ...
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
随机推荐
- 梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画
CSS动画并不是绝对比JavaScript动画性能更优越,开源动画库Velocity.js等就展现了强劲的性能. 一.两者的主要区别 先开门见山的说说两者之间的区别. 1)CSS动画: 基于CSS的动 ...
- 隐私泄露杀手锏 —— Flash 权限反射
[简版:http://weibo.com/p/1001603881940380956046] 前言 一直以为该风险早已被重视,但最近无意中发现,仍有不少网站存在该缺陷,其中不乏一些常用的邮箱.社交网站 ...
- 搞个这样的APP要多久?
这是一个“如有雷同,纯属巧合”的故事,外加一些废话,大家请勿对号入座.开始了…… 我有些尴尬地拿着水杯,正对面坐着来访的王总,他是在别处打拼的人,这几年据说收获颇丰,见移动互联网如火如荼,自然也想着要 ...
- (JS+CSS)实现图片放大效果
代码很简单,在这里就不过多阐述,先上示例图: 实现过程: html部分代码很简单 <div id="outer"> <p>点击图片</p> &l ...
- Eclipse中启动tomcat报错java.lang.OutOfMemoryError: PermGen space的解决方法
有的项目引用了太多的jar包,或者反射生成了太多的类,异或有太多的常量池,就有可能会报java.lang.OutOfMemoryError: PermGen space的错误, 我们知道可以通过jvm ...
- windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)
本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...
- Linux常用指令指南,终端装逼利器
最近搞了台Macbook Pro,就学习了一下Linux命令,在网上查了些资料,看了本书叫<快乐的 Linux 命令行>,里面涉及到了各个方面的命令. 在此将常用的整理出来,以备将来使用. ...
- 内存映射文件MemoryMappedFile使用
参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...
- 一行代码实现java list去重
1.不带类型写法: 1 List listWithoutDup = new ArrayList(new HashSet(listWithDup)); 2.带类型写法(以String类型为例):1)Ja ...
- Js 数组返回去重后的数据
function removeRepeat(data) { var temp = ""; var mainData = []; for (var i = 0; i < dat ...