browserify 的原理是什么?
比如 testmod.js
module.exports = function(){
return 'test';
}
browserify testmod.js -o build/out.js 后是这样
B(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
module.exports = function(){
return 'test';
}
},{}]},{},[1]);
格式化一下
(function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == "function" && require;
if (!u && a) return a(o, !0);
if (i) return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw f.code = "MODULE_NOT_FOUND",
f
}
var l = n[o] = {
exports: {}
};
t[o][0].call(l.exports,
function(e) {
var n = t[o][1][e];
return s(n ? n: e)
},
l, l.exports, e, t, n, r)
}
return n[o].exports
}
var i = typeof require == "function" && require;
for (var o = 0; o < r.length; o++) s(r[o]);
return s
})({
1 : [function(require, module, exports) {
module.exports = function() {
return 'test';
}
},
{}]
},
{},
[1]);
有没有大神解释一下
1 回复
新手,有错误请指正,勿喷。
其实很多时候,觉得代码很晦涩难懂,个人觉得很大一部分原因是:
- 因为变量名用了一大堆
a,b,c,d
,看得头昏脑涨,晕头转向。 - 用了
(function(){})()
这类匿名函数
写法。 - 用了一堆
call
apply
等改变this
的方法。
那么我们不妨逐步将代码改造成我们(好吧,也许只是我)比较好阅读的写法。
去除匿名函数
var t = {
1: [function (require, module, exports) {
exports.a = function () {
return b.b();
}
}, {}]
}, n = {}, r = [1];
function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == "function" && require;
if (!u && a)return a(o, !0);
if (i)return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw f.code = "MODULE_NOT_FOUND", f
}
var l = n[o] = {exports: {}};
t[o][0].call(l.exports, function (e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
}
return n[o].exports
}
var i = typeof require == "function" && require;
for (var o = 0; o < r.length; o++)s(r[o]);
return s
}
e(t, n, r);
这一步后,抛开function s(o, u)
先,其实代码几乎可以认为简化成了
var t, n, r;
function e(t, n, r){
function s(o, u){}
for (var o = 0; o < r.length; o++){
s(r[o]);
}
return s;
}
e(t, n, r);
到了这一步,代码结构已经变得非常清晰,for循环里执行s方法而已。
我们代入变量值,详细分析下function s
。
代入变量值
var r = [1];
for (var o = 0; o < r.length; o++){
s(r[o]);
}
在这个例子里,这段代码就相当于执行s(1);
而已。
就是这么easy~
再来看function s
。
var o = 1;
var n = {};
var t = {
1: [function (require, module, exports) {
exports.a = function () {
return b.b();
}
}, {}]
};
s(1);
function s(o, u) { // o=1, 根本没有传入u这个参数,u=undefined
if (!n[o]) { //n={}, n[1] = undefined; !n[1]=true
if (!t[o]) { // !t[1] = true,这段if代码不会执行,跳过
var a = typeof require == "function" && require;
if (!u && a)return a(o, !0);
if (i)return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw f.code = "MODULE_NOT_FOUND", f
}
var l = n[o] = {exports: {}};
t[o][0].call(l.exports, function (e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
}
return n[o].exports
}
于是,我们可以先把无关的一大段if代码删掉吧,好看点。
function s(o, u) {
if (true) {
var l = n[o] = {exports: {}};
t[o][0].call(l.exports, function (e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
}
return n[o].exports
}
到了现在,代码唯一的难点,就是call的用法了。
call的用法
function Man(name){
this.name = name;
this.fav = 'charming lady';
this.love = function(){
console.log(this.name, 'love', this.fav);
}
}
var jinceon = new Man('jinceon');
jinceon.love(); //jinceon love charming lady
var love = jinceon.love;
love.call(jinceon); //jinceon love charming lady
//可以看到 jinceon.love() 和 love.call(jinceon) 是等价的
var xiaoMing = {name:'小明', fav:'handsome man'};
love.call(xiaoMing); //小明 love handsom man
一句话,call 可以改变this的指向。关于call和apply以及bind,请网上搜索自行学习。
我们先把call关键字替换掉吧。
xiaoMing.love();//xiaoMing的确没有love这个方法,但请不要在意这些细节
或者写出这样,你会开心点?
love(); //this->xiaoMing
再次回到正文,看这段代码,继续代入变量
function s(o, u) {
var l = n[o] = {exports: {}};
t[o][0].call(l.exports, function (e) {
var n = t[o][1][e];
return s(n ? n : e)
}, l, l.exports, e, t, n, r)
return n[o].exports
}
//变成下面这样
var o = 1;
var yourModule = t[o][0] = function (require, module, exports) {
exports.a = function () {
return b.b();
}
}
var r = function (e) {
var n = t[o][1][e];
return s(n ? n : e)
}
function s(o, u) {
var l = n[o] = {exports: {}};
yourModule.call(l.exports, r, l, l.exports, e, t, n, r)
return n[o].exports
}
//实际上yourModule只用到了3个形参,我们把传入的其他参数先无视
function s(o, u) {
var l = n[o] = {exports: {}};
yourModule.call(l.exports, r, l, l.exports)
//yourModule(r, l, l.exports); //this->l.exports
return n[o].exports
}
//替换掉call
function s(o, u) {
function yourModule(require, module, exports) {
exports.a = function () {
return b.b();
}
}
var l = {exports: {}};
yourModule(r, l, l.exports); //this->l.exports
return n[o].exports
}