前言

在写一个懒加载插件时,遇到一个坑,就是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之坑的更多相关文章

  1. 偶遇vue-awesome-swiper的坑

    最近用vue重构一个移动端的项目,碰到了不少坑,今天拿移动端最著名的轮播插件swiper为例来说,由于这个项目没用UI库,纯手写的样式,沿用老的插件,自然而然的选择了vue-awesome-swipe ...

  2. 彻底理解js中this的指向,不必硬背。

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...

  3. this指向详解及改变它的指向的方法

    一.this指向详解(彻底理解js中this的指向,不必硬背) 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是 ...

  4. 详解lastindex,正则test()与全局匹配g偶遇,带来一会true一会false的坑

    一.简单的需求与奇怪的问题 周一接到需求文档,产品分类页的输入框,需要加一个智能下拉提醒的功能,大概就是用户输入啥,找到符合输入字段的产品名,进行下拉推荐,同时将此字段标红,有点类似于百度搜索的智能提 ...

  5. 【转】Vue 脱坑记 - 查漏补缺(汇总下群里高频询问的xxx及给出不靠谱的解决方案)

    前言 文章内容覆盖范围,芝麻绿豆的破问题都有,不止于vue; 给出的是方案,但不是手把手一字一句的给你说十万个为什么! 有三类人不适合此篇文章: “喜欢站在道德制高点的圣母婊” – 适合去教堂 “无理 ...

  6. Android,我待你入初恋啊,你就别坑我了!

    最近做了好多东西,东忙忙,西茫茫,ms最后都空欢喜一场. 1.小黄图,说是小黄图,其实只是网上爬下来的写真阿自拍阿什么的,绝对没有反党反共淫秽内容.后来的后来,admob被google停用了,不开心. ...

  7. Vue 脱坑记

    问题汇总 Q:安装超时(install timeout) 方案有这么些: cnpm : 国内对npm的镜像版本 /* cnpm website: https://npm.taobao.org/ */ ...

  8. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  9. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

随机推荐

  1. java中的字符串相关知识整理

    字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...

  2. UWP中新加的数据绑定方式x:Bind分析总结

    UWP中新加的数据绑定方式x:Bind分析总结 0x00 UWP中的x:Bind 由之前有过WPF开发经验,所以在学习UWP的时候直接省略了XAML.数据绑定等几个看着十分眼熟的主题.学习过程中倒是也 ...

  3. Android总结之链式调用(方法链)

    前言: 最近在学习总结Android属性动画的时候,发现Android的属性动画设计采用了链式调用的方式,然后又回顾了一下了以前接触的开源框架Glide也是采用链式调用的方式,还有最近火的一塌糊涂的R ...

  4. Shell碎碎念

    1. 字符串如何大小写转换 str="This is a Bash Shell script." 1> tr方式 newstr=`tr '[A-Z]' '[a-z]' < ...

  5. 【走过巨坑】android studio对于jni调用及运行闪退无法加载库的问题解决方案

    相信很多小伙伴都在android开发中遇到调用jni的各种巨坑,因为我们不得不在很多地方用到第三方库so文件,然而第三方官方通常都只会给出ADT环境下的集成方式,而谷歌亲儿子android studi ...

  6. CSS 3 学习——渐变

    通过CSS渐变创建的是一个没有固定比例和固定尺寸的<image>类型,也就是说是一张图片,这张图片的尺寸由所应用的元素的相关信息决定.凡是支持图片类型的CSS属性都可以设置渐变,而支持颜色 ...

  7. Entity Framework 延伸系列目录

    1.采用MiniProfiler监控EF与.NET MVC项目 2.采用EntityFramework.Extended 对EF进行扩展 3.EntityFramework执行存储过程中遇到的那些坑 ...

  8. [译]处理文本数据(scikit-learn 教程3)

    原文网址:http://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html 翻译:Tacey Won ...

  9. PAT练习题目录

    点题号就能查看题解了,另外代码也放在了开源中国码云上: 甲级:代码集合:https://git.oschina.net/firstmiki/PAT-Advanced-Level-Practise 10 ...

  10. jenkins无法重启tomcat的原因

    在使用Hudson的执行sh脚本的时候,如果sh脚本是一个后台进程,如 Tomcat 这样的服务.如果使用Hudson的默认配置,会发现这些sh 进程有启动的过程,但是不会常驻后台,看Hudson 输 ...