一、使用base_64编码图片或SVG图片代替原始的png与jpeg图片,再像素要求不高的状况下使用jpeg图片代替png图片vue
二、图片懒加载,在页面上的未可视区域能够添加一个滚动条事件,判断图片位置与浏览器顶端 的距离与页面的距离,若是前者小于后者,优先加载。jquery
- 原生JavaScript实现图片的懒加载
- jQuery插件 jquery.lazy
- vue中使用 vue-lazyload
- mint-ui 插件内置懒加载组件
复制代码
三、图片的预加载,若是为幻灯片、相册等,可使用图片预加载技术,将当前展现图片的前一张和后一张优先 下载。初始化的时候得到图片的src以后为每个元素提早添加图片的地址路径。保证再第二张图片显示的时候已经加载到页面当中浏览器
实现方法:循环图片数据,实例化对象的方式建立图片元素 new image() 动态绑定每个image的src属性,并追加到DOM流中
复制代码
JS 中分为七种内置类型,七种内置类型又分为两大类型:基本类型和对象(Object)。bash
基本类型有六种: null,undefined,boolean,number,string,symbol。闭包
对象(Object)是引用类型,在使用过程当中会遇到浅拷贝和深拷贝的问题。app
let a = { name: 'FE' }
let b = a
b.name = 'EF'
console.log(a.name) // EF
复制代码
typeof 对于基本类型,除了 null 均可以显示正确的类型模块化
想得到一个变量的正确类型,能够经过 Object.prototype.toString.call(xx)函数
- 新生成了一个对象
- 连接到原型
- 绑定this
- 返回新对象
复制代码
function create() {
// 建立一个空的对象
let obj = new Object()
// 得到构造函数
let Con = [].shift.call(arguments)
// 连接到原型
obj.__proto__ = Con.prototype
// 绑定 this,执行构造函数
let result = Con.apply(obj, arguments)
// 确保 new 出来的是个对象
return typeof result === 'object' ? result : obj
}
复制代码
判断对象属于某一个类,回去查找对象的constructor的prototype
复制代码
function foo() {
console.log(this.a)
}
var a = 1
foo()
var obj = {
a: 2,
foo: foo
}
obj.foo()
复制代码
以上二者状况 this
只依赖于调用函数前的对象,优先级是第二个状况大于第一个状况优化
如下状况是优先级最高的,this
只会绑定在 c
上,不会被任何方式修改 this
指向ui
var c = new foo()
c.a = 3
console.log(c.a)
复制代码
还有种就是利用 call,apply,bind 改变 this,这个优先级仅次于 new
function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()())
复制代码
箭头函数实际上是没有 this 的,这个函数中的 this 只取决于他外面的第一个不是箭头函数的函数的 this。在这个例子中,由于调用 a 符合前面代码中的第一个状况,因此 this 是 window。而且 this 一旦绑定了上下文,就不会被任何代码改变
一、做用域
种类:JS中有三种做用域,全局做用域,函数做用域,ES6新推出块级做用域
概念:一个变量的可访问规则,再函数建立的时候就已经定义好做用域,整个的JS文件执行有一个最外层的全局做用域(window)
使用: 本做用域内部的全部变量均可已再本做用域内部访问,外部没法访问。内部可访问上级做用域变量,本做用于内部所用使用var声明的变量会有一个做用域提高的过程,let与const声明的变量没有变量提高
二、做用域链
一个变量的访问规则的链式操做
能够把它理解成包含自身变量对象和上级变量对象的列表,经过 [[Scope]] 属性查找上级变量
当访问一个变量的时候,先在本做用域内部进行查找,若是没有去上级做用域进行查找,直到全局做用域window下面,都没有,返回undefined
一、特色:
内层做用域能够访问外层做用域的变量
闭包就是可以读取其余函数内部变量的函数
函数 A 返回了一个函数 B,而且函数 B 中使用了函数 A 的变量,函数 B 就被称为闭包。
闭包函数引用的变量是存储在堆上的,因此说,当闭包函数弹出调用栈以后,闭包返回的函数依然能调用到闭包函数的变量
二、优势:
使用闭包能够造成独立的空间,延长变量的生命周期,保存中间状态值
能够封装一些私有变量,外部没法进行直接访问(例如用户登录状态计数器)建立当即执行函数(闭包)实现JS模块化封装
解决var声明的循环语句变量没法长久保存的问题
三、缺点:
滥用闭包函数会形成内存泄露,由于闭包中引用到的包裹函数中定义的变量都 永远不会被释放,因此咱们应该在必要的时候,及时释放这个闭包函数,将再也不使用的闭包引用设置为null;
因为函数内部的变量都被保存在内存中, 会致使内存消耗大;
四、相关代码:
for ( var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
// 每次循环都会输出 5 没法保存变量
复制代码
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
}
// 建立当即执行函数,造成闭包,保存每一次循环的变量
复制代码
// 解决下列调用打印每次都是5的问题
var arr = []
for (var i = 0; i < 5; i++) {
arr.push(function() { console.log(i) })
}
// 使用闭包的方式
for (var i = 0; i < 5; i++) {
(function(i) {
arr.push(function() {
console.log(i)
})
})(i)
}
// 使用ES6的let建立块级做用域
for (let i = 0; i < 5; i++) {
arr.push(function() {
console.log(i)
})
}
// 使用setTimeout的第三个参数
for (let i = 0; i < 5; i++) {
setTimeout(function() {
arr.push(function() {
console.log(i)
})
}, 0,i)
}
复制代码