2017.08.25
new
闭包
使用场景:模拟面向对象中的类、立即执行函数、模拟方法工厂、模拟块级作用域、模拟私有变量
闭包的内存回收
影响闭包被回收的因素:内部函数是否使用了外部函数的变量
<button id="btnGetInner">getInner</button>
<button id="btnRunInner">runInner</button>
var getLargeObj = function (size) {
var arr = [];
var intSize = parseInt(size);
for (var i = intSize.length - 1; i >= 0; i--) {
for (var j = 199999; j >= 0; j--) {
arr.push('abcdefghijklmnopqrstuvwxyz');
}
}
return intSize;
}
function outer() {
console.log('outer');
var largeObject;
if (!!window.ActiveXobject || "ActiveXobject" in window) {
// ie 监控内存变化很方便,所以直接使用较大内存,了解内存的变化曲线
largeObject = getLargeObj('100MB');
} else {
// 在 chrome 等浏览器下,监控内存不方便,所以保存1m的内存快照,来对比内存的变化
largeObject = getLargeObj('1MB');
}
function help() {
return largeObject;
// eval('')
}
// inner 函数
return function () {
console.log('inner');
return largeObject;
}
}
document.getElementById('btnGetInner').onclick = function () {
inner = outer();
// 仅使用于 IE 浏览器,其他浏览器使用调试工具手动回收
if (window.CollectGarbage) {
CollectGarbage();
}
}
document.getElementById('btnRunInner').onclick = function () {
if (inner) {
inner();
}
}
- 闭包中的没有被引用的变量会被垃圾回收,被引用的变量不会被回收。
- 即使闭包中没有变量被引用,但是使用了 eval() 函数,会保留闭包中所有的局部变量以避免产生不可预期的结果,所以不回收闭包变量
- 内部函数中使用 window.eval() ,只能访问到全局变量,所以闭包中的变量会被回收
- 不仅返回的内部函数,其他被定义的内部 函数中使用了外部函数中的变量或 eval() 函数,也不能回收闭包中的内存
是否应该使用闭包? 在最新版的浏览器下,是可以使用闭包的。而在旧版中,特别是旧版IE中,不建议使用闭包。
如何高效地使用闭包?
- 内部函数尽量少使用外部函数的局部变量
- 内部函数尽量不要直接调用 eval 函数
- 在退出函数之前,将不使用的局部变量全部删除或设置为 null ,断开变量和内存之间的联系
关卡挑战:
仔细想想,前3题会输出什么结果,并完成后面两道编码题。(建议完成时间:60分钟)
解题提示:深挖闭包的特性。
// 挑战一
var checkClosure = function() {
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = function() {
return i;
}
}
return arr;
};
var arr = checkClosure();
console.log(arr[0]()); // ???
console.log(arr[1]()); // ???
console.log(arr[2]()); // ???
console.log(arr[3]()); // ???
console.log(arr[4]()); // ???
// 挑战二
var add = function(x) {
var sum = 0;
var fn = function(x) {
if (x) {
sum = sum + x;
return fn;
} else {
return sum;
}
}
return fn;
}
console.log(add(1)(2)(3)(4)(5)()); // ???
// 挑战三
function checkClosure(n, o) {
console.log(o);
return {
checkClosure: function(m) {
return checkClosure(m, n);
}
};
}
var a = checkClosure(0);a.checkClosure(1);a.checkClosure(2);a.checkClosure(3); // ???,???,???,???
var b = checkClosure(0).checkClosure(1);b.checkClosure(2);b.checkClosure(3); // ???,???,???,???
var c = checkClosure(0).checkClosure(1).checkClosure(2);c.checkClosure(3); // ???,???,???,???
var d = checkClosure(0).checkClosure(1).checkClosure(2).checkClosure(3); // ???,???,???,???
// 挑战四
// 定义一个函数 repeat,这个函数能返回一个新函数,调用 repeatedFun ("hello world"),会 alert 十次 hello world, 每次间隔5秒。
function repeat (func, times, wait) {}
var repeatedFun = repeat(alert, 10, 5000);
repeatedFun ("hello world");
// 挑战五
// 定义一个函数 stringconcat, 要求能实现以下功能。
var result1 = stringconcat("a", "b"); // result1 = "a+b"
var stringconcatWithPrefix = stringconcat.prefix("helloworld");
var result2 = stringconcatWithPrefix("a", "b"); // result2 = "helloworld+a+b"
- this
this 在 javascript 中指的是函数执行时的上下文,跟函数定义时的上下文无关。随着函数使用场合的不同,this 的值会发生变化。但是有一个总的原则,那就是 this 指代的是调用函数的那个对象。
- 全局作用域中的this 恒等于 window
- 函数作用域中的 this:外部函数作用域中的 this指代window(严格模式下,禁止使用全局对象,会报 undefined)
- 对象方法中的 this:动态绑定,运行时绑定,并不是定义时绑定
var o = {
name: 'carlsiry',
f: function() {
console.log(this.name);
}
}
o.f(); // carlsiry
function f3() {
console.log(this.name); // 定义时的 this 指代 window
}
var o2 = {
name = 'carlsiry'
};
o2.f = f3;
o2.f(); // carlsiry ,运行时绑定到了 o2 对象,指代 o2
- 闭包中的 this:指代内部函数被调用时的执行环境
- eval() 函数中的this:相当于对象方法
- call() 和 apply() 方法中的this:指代传入的第一个参数对象,如果参数为空则默认指代 window对象
var x = 0;
var a = {x: 2};
var o = {
x: 1,
f: function() {
console.log(x);
}
};
o.f(); // 1
o.f.call(a); // 2
o.f.call(); // 1
- bind() 方法中的 this:永久绑定到bind 的第一个参数
function test() {
console.log(this.name);
}
var foo = test.bind({name: 'carl'});
foo(); // carl
var bar = {
name: 'bar',
test: test,
foo: foo
};
bar.test(); // bar
bar.foo(); // carl
- DOM事件处理函数中的this:当函数使用 addEventListener 作为事件处理函数时,它的this指向触发事件的元素(非IE);当函数使用 attachEvent 作为事件处理函数时,它的 this 指向 window 对象(IE浏览器)
- 内联内联事件处理函数中的this:
<a onclick="alert(this.tagName)">clickMe</a>
指代绑定的DOM的元素(注意如果是匿名函数,那么this 指代 window对象)
关卡挑战:
仔细想想,以下代码会输出什么结果?(建议完成时间:30分钟)
解题提示:
1.深挖 this 的 9 个使用场景。
2.部分挑战第一次执行的结果,会影响到第二次的执行结果。
// 挑战一
(function() {
this.scope = "local";
})();
console.log(window.scope); // ???
// 挑战二
var scope = "global";
var obj = {
scope: "local",
getScope: function() {
return function() {
return this.scope;
};
}
};
console.log(obj.getScope()()); // ???
// 挑战三
var scope = "global";
var obj = {
scope: "local",
getScope: function() {
var that = this;
return function() {
return that.scope;
};
}
};
console.log(obj.getScope()()); // ???
// 挑战四
function a(x) {
debugger;
this.x = x;
return this;
};
var x = a(5);
var y = a(6);
console.log(x.x); // ???
console.log(y.x); // ???
// 挑战5五
function obj() {
this.scope = "local";
return "global";
}
var obj = new obj();
console.log(obj); // ???
// 挑战六
scope = "global";
var obj1 = {
scope: "local1",
getScope: function() {
console.log(this.scope)
}
};
var obj2 = {
scope: "local2"
};
(obj2.getScope = obj1.getScope)(); // ???
- 切图技巧
理解设计稿的“一页多状态”和交互方式
- 最小原则:背景平铺、合成雪碧图
最适原则:图片格式(jpg最小,png最真,gif最活,ico最细)
美化表单以及扒站技巧
input { width: 200px; height: 30px; padding: 0 4px; border: 1px #ccc solid; border-radius: 2px; } /* focus */ input { outline: none; } input::-webkit-input-placeholder { color: #ccc; }
扒站技巧:Webzip, HTTrack Website Copier, teleport pro, scrapbook(火狐附加组件)
网页分析技巧:转化路径分析、营销效果分析、来源分析
视屏缩略图布局与样式
<style type="text/css">
.box{
width: 170px;
font-size: 12px;
color: #3a3a3a;
}
.box .cut-img{
height: 110px;
position: relative;
margin-bottom: 10px;
}
.box .cut-img p{
color: #fff;
margin: 0;
position: absolute;
left: 0;
bottom: 0;
width: 90%;
padding:5px 5%;
}
.box .cut-img p i{
display: inline-block;
width: 0;
height: 0;
font-size: 0;
line-height: 0;
border:5px transparent solid;
border-left: 8px #fff solid;
vertical-align: middle;
}
.box .cut-img p span{
display: inline-block;
vertical-align: middle;
}
.box h3{
margin:0 0 8px;
}
.box h3 a{
color: #3a3a3a;
text-decoration: none;
}
.box h3 a:hover{
color: #e73c31;
}
.box p.muted{
color: #909090;
margin:0;
}
</style>
<div class="box">
<div class="cut-img">
<img src="cut_pic.jpg" />
<p><i></i><span>1,042万</span></p>
</div>
<h3><a href="#">评价女王</a></h3>
<p class="muted">看“女王”怎么撩五男!</p>
</div>
- SEO 优化:
- 关键词分析
- 网站目录、页面优化
- 内容发布和链接布置
- 建立网站地图(SiteMap)