偶遇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源码解析 前面 ...
随机推荐
- 说说Makefile那些事儿
说说Makefile那些事儿 |扬说|透过现象看本质 工作至今,一直对Makefile半知半解.突然某天幡然醒悟,觉得此举极为不妥,只得洗心革面从头学来,以前许多不明觉厉之处顿时茅塞顿开,想想好记性不 ...
- Java 线程
线程:线程是进程的组成部分,一个进程可以拥有多个线程,而一个线程必须拥有一个父进程.线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不能拥有系统资源.它与父进程的其他线程共享该进程的所有资 ...
- win7安装时,避免产生100m系统保留分区的办法
在通过光盘或者U盘安装Win7操作系统时,在对新硬盘进行分区时,会自动产生100m的系统保留分区.对于有洁癖的人来说,这个不可见又删不掉的分区是个苦恼.下面介绍通过diskpart消灭保留分区的办法: ...
- Xshell 连接CentOS服务器解密
平台之大势何人能挡? 带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4822808.html Xshell生成密钥key(用于Linux 免密码登录)htt ...
- 深究标准IO的缓存
前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...
- javascript单元测试框架mochajs详解
关于单元测试的想法 对于一些比较重要的项目,每次更新代码之后总是要自己测好久,担心一旦上线出了问题影响的服务太多,此时就希望能有一个比较规范的测试流程.在github上看到牛逼的javascript开 ...
- Http请求
HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. 请求报文 一个HTTP请求报文由请求行(request line ...
- redis成长之路——(二)
redis操作封装 针对这些常用结构,StackExchange.Redis已经做了一些封装,不过在实际应用场景中还必须添加一些功能,例如重试等 所以对一些常功能做了一些自行封装SERedisOper ...
- 【手记】注意BinaryWriter写string的小坑——会在string前加上长度前缀length-prefixed
之前以为BinaryWriter写string会严格按构造时指定的编码(不指定则是无BOM的UTF8)写入string的二进制,如下面的代码: //将字符串"a"写入流,再拿到流的 ...
- mysql 5.7中的用户权限分配相关解读!
这篇文章主要介绍了MySQL中基本的用户和权限管理方法,包括各个权限所能操作的事务以及操作权限的一些常用命令语句,是MySQL入门学习中的基础知识,需要的朋友可以参考下 一.简介 各大帖子及文章都会讲 ...