阅读前需要了解:? ?
????ES5严格模式:‘use strict’
? ? eval的间接引用和直接引用
? ? 逗号运算符的作用
????现在网上已经有很多的插件,他们不仅外观漂亮而且性能也好,插件再多也架不住产品的想法多,但是在开发过程中很多时候我们需要针对自己的项目,对一些常用的功能进行封装,这样大大提高了代码复用率。
? ? 封装过程中会有这么一步,是把自己的函数暴露给当前作用于或者全局。
????一般推荐暴露给当前作用域,也就是this的指向。
;(function(){
? ? var fn = function(){......};//我自己的插件方法
????//暴露给全局作用域
????window.fn = fn;
? ? //或者是暴露给当前函数的外层作用域(推荐)
? ? this.fn = fn;
}());
逼格高一点的会在这个自执行函数IIF里面放一个,暂且不考虑window还是当前作用域。
!('myFn' in window) && (window.myFn = myFn);
这里的(‘myFn’ in Obj)方法是判断window下面有没有键为‘myFn’的方法,如果有则返回true。
为了提高插件中语法的严谨性好多人都在自执行函数内部或者局部使用严格模式"use strict";
;(function(){
????"use strict"
}());
严格模式的特点不在这里做过多的赘述,但是在这里有一点要清楚,
在严格模式下会抑制 this
举个例子:
;(function()
? ? "use strict";
? ? console.log(this)
})
//输出的结果为undefined
????说了这么多,我们今天的重点来了:如何解决这一问题,就需要我们的eval来获取当前上下文对象
? ? js 中 eval() 函数的作用就是讲函数内的参数当做代码来执行。
? ? 比如eval('1+1')得到的值为2,然而如果直接打印‘1+1’他就是一个字符串,eval(‘this’)得到的就是this。
? ? 很多插件中都有这句话(0,eval)('this')。这时候就涉及到了eval的直接引用和间接引用以及逗号表达式。逗号表达式是执行顺序等级最低的,如果(1,eval)会先执行逗号前面的式子(逗号前面也会当做一个表达式),最终会执行eval()。
????但是(0,eval)('this')和eval('this')同样是执行eval,但他们有什么区别呢,下面是间接引用和直接引用的方法。
间接引用
(1, eval)('...')
(eval, eval)('...')
(1 ? eval : 0)('...')
(__ = eval)('...')vare = eval; e('...')
(function(e) { e('...') })(eval)
(function(e) {returne })(eval)('...')
(function() { arguments[0]('...') })(eval)this.eval('...')this['eval']('...')
[eval][0]('...')
eval.call(this, '...')
eval('eval')('...')
直接引用
eval('...')
(eval)('...')
(((eval)))('...')
(function() { return eval('...') })()
eval('eval("...")')
(function(eval) { return eval('...'); })(eval)
with({ eval: eval })eval('...')
with(window) eval('...')
? ? 通过上面大致看一眼,我们可以理解,间接引用大部分都是表达式,表达式计算出来的是一个值,而直接引用就是一个引用,个人理解由于在严格模式下对this的引用是有限制的,所以如果转换成了值就可以直接获取到正确的this指向了。(如果异议请留下您的宝贵意见)
????所以我们需要间接引用eval来获取准确的this指向,才可以将他暴露给当前函数的作用域。
? ??(0,eval)('this')不管逗号前面是什么数字,都可以。
????所以,逼格再高一点的会在这个自执行函数IIF里面放
;(function(){
? ? 'use strict'? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //设置为严格模式
? ? var myFn = function(){......};? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //我的插件方法
????_global = (function(){ return this || (0, eval)('this'); }());? ? ? ? ? ? ? ? ? ? //查找当前作用域,也就是this的指向,也就是找到顶层对象;这里不了解的可以查看阮一峰老师的《 ECMAScript 6 入门 》第一章,“global对象 ”
????!('myFn' in _global) && (_global.myFn = myFn);? ? ? ? ? ? ? ? ? ? ? ? ? ? //暴露
}())
? ? 逗号表达式问题扩展:
? ?如何不通过第三个变量来改变ab两个变量的值?
var a = 'a' , b = 'b';
a = [b,b=a][0]
console.log(a,b)//打印出b,a