webpack结构
注意:js 中的函数其实是对象,函数名是对 Function 对象的引用webpack结构类似如下样子:
示例1:
function (x){
function xx(yy){ //此xx方法是模块加载器
x[yy].call(xx0,xx1,xx2,xx3); //必有一个加载模块的方法(不一定是call, 也可能是apply)
} //这里的xx0是一个对象, xx1,xx2,xx3参数分别对应着下方模块中的x1,x2,x3参数
//xx(0) //可以调用第一个模块(即选择下面方法数组中的方法并执行)
}([ //这里传的是数组
function(x1,x2,x3) {},
function(x1,x2,x3) {},
function(x1,x2,x3) {}
]); //传一系列的方法数组 (即这些都是模块)
示例2:
function (x){
function xx(yy){ //此xx方法是模块加载器
x[yy].call(xx0,xx1,xx2,xx3); //必有一个加载模块的方法(不一定是call, 也可能是apply)
} //这里的xx0是一个对象, xx1,xx2,xx3参数分别对应着下方模块中的x1,x2,x3参数
//xx("fun1") //可以调用第一个模块(即选择下面方法对象中的方法并执行)
}({ //这里传的是对象
fun1:function(x1,x2,x3) {},
fun2:function(x1,x2,x3) {},
fun3:function(x1,x2,x3) {}
}); //传一系列的方法对象 (即这些都是模块)
call和apply方法
apply()和call差不多,只不过apply第二个参数必须传入的是一个数组,而call 第二个参数可以是任意类型,且它们的第一个参数都必须为一个对象。
xxx.call(对象, “参数1”, “参数2”);
xxx.apply(对象, [‘参数1’, ‘参数2’]);
用法
function add (x, y)
{
console.log (x + y);
}
function sub (x, y)
{
console.log (x - y);
}
add.call (sub , 1, 1); //2
解释:用 add 来替换 sub,add.call(sub,1,1) == add(1,1) ,所以运行结果为:2
function Animal(name){
this.name = name;
this.showName = function(){
alert(this.name);
}
}
function Cat(name){
Animal.call(this, name);
}
var cat = new Cat("Black Cat");
cat.showName();
解释:Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么 Cat中不就有Animal的所有属性和方法了吗,Cat对象就能够直接调用Animal的方法以及属性了。
在js逆向中的应用
某js中外层的函数加密模块:
function(t, e, i) {
var s;
s = function(t, e, s) {
function n() {
"undefined" != typeof r && (this.jsencrypt = new r.JSEncrypt,
this.jsencrypt.setPublicKey("省略"))
}
var r = i(4); //观察这个i方法是什么
n.prototype.encode = function(t, e) {
var i = e ? e + "|" + t : t;
return encodeURIComponent(this.jsencrypt.encrypt(i))
}
,
s.exports = n
}
.call(e, i, e, t),
!(void 0 !== s && (t.exports = s))
}
观察上方的i
方法到底是什么?
某js中加载器部分代码:
function e(s) { //方法
if (i[s])
return i[s].exports;
var n = i[s] = { //对象
exports: {}, //对象
id: s,
loaded: !1
};
//这里的e是指递归调用自身, 作用: 将加载函数又传给了模块,让模块也拥有了加载其他函数的功能
//同时上方的i方法所属的外层函数加密模块,也是由这里的call加载调用的
return t[s].call(n.exports, n, n.exports, e), //在此处打断点,如果断不住,就说明是动态加载的
n.loaded = !0,
n.exports
}
上方的i
是function(t, e, i)
函数中的第三个参数,因为call方法中第一个参数必须为一个对象,所以上方的i
又对应着call(n.exports, n, n.exports, e)
中的第4个参数,即e
。
- 结论:上方的
i
方法就是这里的e
方法(也就是加载器
本身) - 注意:若为
i(20)
,则就是调用方法对象(即模块)中的20
所对应的函数