啸羽程序园

用了多年javascript,用过的插件数不胜数,很多插件用起来方便易用,那么怎样开发自己的高大上插件呢,看插件的源码有一些语法觉得很高深莫测吗?谨以此文解开javascript插件开发的神秘面纱。

开发插件首先要深刻理解变量、作用域、函数和闭包。

js中一切都可以当成变量。方法也可以是变量,这点很重要。废话少说看例子

<html>
<head>
<script type=”text/javascript”>
function parent(p){
function children(c){
return p + c;
}
return children;
}
var T= parent(10);
var result = T(20);
console.log(result);//输出结果 30
</script>
</head>

<body>
</body>

</html>

这是一个神奇的例子,所蕴含的知识点贯穿全文。

方法也是变量在哪体现呢?var obj = parent(1); 这句话,方法parent的返回值 return children 返回的就是方法,obj变量就是一个方法,这样result = T(20) 就很好理解了,children(20) 输出结果10+10=30

 

接下来简单看看作用域:

什么是作用域,域听起来很高深的一个字,其实就是变量的作用范围,js中通常有两种情况:全局变量 和 局部变量

定义在函数内部的变量是局部变量,定义在函数外部的变量是全局变量。那么怎么理解函数内的作用范围呢?继续看这个神奇的例子:

var v = “我是全局变量”

function parent(p){

var vp = “我是父局部变量”
console.log( v)      //我是全局变量
console.log( vp)   //我是父局部变量

console.log( vc)   //vc is not defined

       function children(c){

var vc = “我是子局部变量”
console.log( v)    //我是全局变量
console.log( vp)   //我是父局部变量
console.log( vc)   //我是子局部变量

               return p + c;
    }
    return children;
}

console.log( v)    //我是全局变量
console.log( vp)  //vc is not defined
console.log( vc)  //vc is not defined

注释就是输出结果,这样就清晰地知道局部变量的作用范围了吧。这就是域。

补充一个注意事项:(如果再函数内声明变量时候不用var,变量为全局变量!很重要很奇怪。比如:var vp = “我是父局部变量”改成 –>vp = “我是父局部变量”,那么vp就是全局变量,作用域和v一模一样!)

明白了作用域,我们换个角度看这个万能例子,父函数嵌套子函数,子函数能访问父函数声明的变量(也能访问父函数传递进来的参数变量),父函数不能访问子函数声明的变量,换句话说:子函数形成了一个相对独立的环境(空间)使得它自身的变量只能由它自己来访问,这里嵌套子函数就形成了一个闭包。闭包的特点是啥:父函数能调用子函数,但是不能访问子函数的局部变量,子函数能访问父函数声明的变量,类似java的继承。总结一点:函数不就是闭包嘛。

闭包的应用场景:

关于闭包在开发中的使用,最多的体现还是在 Javascript 插件的开发上面。使用闭包可以避免变量污染。也就是说你在闭包中使用的变量名称不会影响到其他地方同样名称,换个角度来讲,我将我嵌套函数内部的变量给保护起来了,外部没办法随便修改我内部定义的变量了。再看万能小例子:

function parent(){
    function children(p){
var c = 10
    return p + c;
    }
    return children;
}

var c = 100 //全局变量c=100
var result =parent()(c);  //注意这里的调用很有意思
console.log(c);//输出结果 100 外部变量
console.log(result);//输出结果110,内部变量c+外部传递的100=110

虽然全局变量也叫c但是闭包保护了内部变量c=10,传进来的变量没有改变闭包内的变量值,设想,如果去掉子函数中的

var c = 10 变量声明会发生什么?结果是什么?

好了,编写插件准备完毕,接下来先从HelloWorld走入插件世界。

 

//声明插件
var plugin =(function(){
    function _helloworld(str){
        console.log(str);
    };
    return{
        helloworld: _helloworld,
    };
})();
//使用插件
plugin('HelloWorld!')  //输出我们久违的‘HelloWorld!’

接下来一步步分析代码:
(function{
    //code
})();
这叫做:自调用匿名函数  -----这不就是闭包嘛。
作用:防止插件用户定义函数与插件冲突---这不就是闭包的作用嘛。
等价于:
var func = function(){ //code } func();
最后面的小括号等价func()执行函数

再看这里:
return{ 
    helloworld: _helloworld, 
};
这里是类似java中一个接口声明了很多方法,我提供了plugin的接口,接口中有各种各样的方法如:helloworld

再来稍微修改下神奇的小例子更深入的理解接口和方法(为了更清晰地解释本人对比java的概念,不要混淆)
//声明插件
var plugin =(function(){
    function _helloworld(str){
        console.log(str);
    };
    function _hellombsh(str){ 
        console.log(str); 
    };
    return{
        helloworld: _helloworld,
        hellombsh: _hellombsh
    };
})();
//使用插件
plugin.helloworld('HelloWorld!')  //输出我们久违的‘HelloWorld!’
plugin.hellombsh('欢迎来到梦笔生花!') //输出我们激动人心的‘欢迎来到梦笔生花!’

ok!这就是插件,我们扩展了插件增加了hellombsh方法,就这么简单。


这是一种比较简洁好用的自定义插件方式,还有其他不同写法,摘抄几段仅供参考:

1.面向对象思想 类方式
//自定义类    
function plugin(){}

//提供默认参数
plugin.prototype.str = "default param";

//提供方法(如果不传参,则使用默认参数)
plugin.prototype.firstFunc = function(str = this.str){
    alert(str);
}

//创建"对象"
var p = new plugin();
//调用方法
p.firstFunc("Hello ! I am firstFunc");//Hello ! I am firstFunc
p.firstFunc();//default param
2.闭包方式
var plugin =(function(){
    function _firstFunc(str){
        alert(str);
    };
    return{
        firstFunc: _firstFunc,
    };
})();
3.第二种方式上的一些变化 貌似更加规范?
(function(){
    //定义一些默认参数
    var _options={
        default_word:"default hello"                
    }

    //定义一些api
    var _plugin_api = {
        firstFunc:function(str = _options.default_word){
            alert(str);
            return this;//返回当前方法
        },
        secondFunc:function(){
            alert("secondFunc");
            return this;//返回当前方法
        }
    }
    //这里确定了插件的名称
    this.CJPlugin = _plugin_api;
})();

CJPlugin.firstFunc("hello");//hello
CJPlugin.firstFunc();//default hello
CJPlugin.secondFunc();//secondFunc
好了,javascript的自定义插件和闭包就介绍到这里,任何语言的任何知识点深入研究都是变化无穷
妙用无穷的,希望本文能够为广大js爱好者更好地理解闭包和插件尽些绵薄之力。

Hi, I’m shen, 啸羽