javascript面向对象和设计模式

一、注释写法

1 /*
2  * @author: 作者
3  * @action:  组件的作用
4  * @date:    创建日期
5  * 
6  * Options :  events  delay   // 属性
7  * Methods : currentShow  getContent    // 方法
8  * Events : beforeClick  afterClick   // 自定义事件或系统事件
9  */

一、面向对象

一、面向对象的一些重要的方面

  1、对象引用  2、作用域  3、闭包  4、上下文

  引用引用就是指向对象实际位置的指针,多个变量可以引用一个对象

1 <script>
2     var obj = new Object();     // 创建一个新类
3     var objRef = obj;       // 将引用地址赋给这个变量
4     obj.one = true;         // 创建类的属性
5     alert(obj.one === objRef.one);      // 返回true
6 </script>

  作用域是JS中一个难处理的特性,在JS里作用域由函数所约束,而不由块约束(如for,if,while语句)

 1 <script>
 2     // 例1:
 3     var foo = "test";
 4     if(true){
 5         var foo = "new test";       // 这里仍然是全局变量
 6     }
 7     alert(foo === "new test");      // 所以返回true
 8 
 9     // 例2:
10     var foos = "test";
11     function test(){
12         var foos = "new test";      // 这里是局布变量
13     }
14     alert(foos === "new test");     // 所以为false
15 </script>

  全局变量都是window的属性,定义的函数都是window的方法.

  隐式全局变量

1 <script>
2     var foos = "test";
3     function test(){
4         name = "new test";          // 在函数里没有用var定义的变量都为全局变量
5     }
6     alert(name === "new test");     // 返回true
7 </script>

  闭包:内层函数可以引用存在于包绕它的函数变量 

  上下文:是通过变量this工作

 1 <script>
 2     var obj = {
 3         yes: function(){
 4             this.val = true;
 5         },
 6         no : function(){
 7             this.val = false;
 8         }
 9     }
10     // 如果直接调用obj.val 对象obj没有这个属性所以为null
11     // 将运行yes方法后this会指向obj上,这时可以调用obj.val
12     obj.yes();
13     alert(obj.val);         // 返回true
14 </script>

  改变上下文

 1 <script>
 2     function changeColor(colors) {
 3         console.log(this);
 4         this.style.color = colors;
 5     }
 6     // 在window对象上调用这个函数,因为window没有style对象
 7     // new changeColor("white");
 8 
 9     // 通过call来改变this指针的指向
10     var box = document.getElementById("box");
11     changeColor.call(box, "red");
12 </script>

二、面向对象的基础

  1、创建对象和对象属性方法的两个例子

 1 <script>
 2     // 方法一
 3     var obj = new Object();
 4     // 创建对象公用属性和方法
 5     obj.name = "哈哈";
 6     obj.sayName = function(){
 7         alert(this.name);
 8     }
 9     obj.sayName();
10 
11     // 方法二
12     var obj = {
13         name : "哈哈",
14         sayName : function(){
15             alert(this.name);
16         }
17     }
18     obj.sayName();
19 </script>

  2、公有属性和方法、私有属性和方法

 1 <script>
 2     // 公有属性、方法
 3     function User(name, age){
 4         this.name = name;       // 公有属性
 5         this.age = age;
 6     }
 7     User.prototype.getName = function(){    // 公有方法,通过prototype对象
 8         return this.name;
 9     }
10     User.prototype.getAge = function(){
11         return this.age;
12     }
13     var user = new User("哈哈", 30);
14     alert(user.getName() == "哈哈");       // 返回true;
15 
16     // 私有属性、方法
17     function Class(student, teacher){
18         this.student = student;
19         this.teacher = teacher;
20         var current = 0;            // 私有属性
21 
22         function getCurrent(){
23             return current;
24         }
25     }
26     Class.prototype.getName = function(){
27         // console.log(current);       // 报错,current为私有属性的,返回undefined
28         return this.student;
29     }
30     var className = new Class("aaa", "bbb");
31     className.getName();
32     // className.getCurrent();            // 报错,私有方法不能被外界所访问
33 </script>

  3、特权方法:是用来访问和改变私有变量的方法

 1 <script>
 2     function User(name, age){
 3         this.name = name;
 4         this.age = age;
 5         var year = 2013;
 6         this.getYear = function(){      // 特权方法,不能放到prototype中,因为作用域会找不到year
 7             return year;
 8         }
 9     }
10     var user = new User("哈哈", 30);
11     alert(user.getYear());          // 返回2013;
12 </script>

三、命名空间

 1 <script>
 2     // 创建一个全局的命名空间
 3     var YAHOO = {};
 4 
 5     // 设置一个子的命名空间
 6     YAHOO.util = {};
 7     
 8     YAHOO.util.Event = {
 9         addEventListener:function(){ }
10     }
11 
12     // 调用方法
13     YAHOO.util.event.addEventListener();
14 </script>

三、!=、== vs !==、===

  在javascript里,null、0、""、false和undefined全部彼此相等(==),因为他们计算的值都为false;

 1 <script>
 2     console.log(typeof null);       // 返回Object
 3     console.log(typeof undefined);  // 返回undefined
 4 
 5     // 常见问题
 6     console.log(null == undefined); // false;
 7     console.log("" == undefined);   // false;
 8     console.log(0 == undefined);    // true;
 9     console.log(String == undefined);   // false;
10     console.log(String == null);    // false;
11     console.log(String === Object); // false;
12 </script>

一、富有表现力的javascript

一、在编程时你可以写采用函数式编程风格,也可以写成复杂一点的面象对象编程风格

二、链式调用

  如jQuery采用的就是链式调用,$("#name").find("<p>").addClass("active");

 1 <div class="box" id="box">14077期任选9场中头奖3894注</div>
 2 <input type="button" value="添加" id="add">
 3 <input type="button" value="删除" id="del">
 4 
 5 <script>
 6     function getId(id){
 7         return document.getElementById(id);
 8     }
 9 
10     var oAdd = getId("add");
11     var oDel = getId("del");
12 
13     function Chain(oId){
14         this.box = getId(oId);
15     }
16 
17     Chain.prototype = {
18 
19         // 添加class值
20         addClass: function(claName){
21             console.log(this.box);
22             var sClass = this.box.getAttribute("class");
23             this.box.className = sClass+ " " +claName;
24             return this;
25         },
26 
27         // 删除class值
28         removeClass: function(claName){
29             var sClass = this.box.getAttribute("class");
30             var delClass = sClass.replace(/"claName"/, "");
31             this.box.className = delClass;
32             return this;
33         },
34 
35         // css读写样式
36         css: function(pro, val){
37             var t = this;
38             if(arguments.length == 1){
39                 console.log("参1")
40                 var cssValue = t.getStyle(this.box, pro);
41                 return cssValue;
42             }
43             if(arguments.length == 2){
44                 console.log("参2");
45                 t.box.style[pro] = val + "px";
46             }
47             return this;
48         },
49 
50         // 获取样式
51         getStyle: function(obj, attr){
52             if(obj.currentStyle){
53                 return obj.currentStyle[attr];
54             }
55             else{
56                 return getComputedStyle(obj, false)[attr]
57             }
58         }
59 
60 
61     }
62 
63     window.$ = function(id){
64        return new Chain(id);
65     }
66 
67     oAdd.onclick = function(){
68         var getWidth = $("box").addClass("active").css("width");
69         console.log(getWidth);
70     }
71 
72     oDel.onclick = function(){
73         $("box").addClass("show").removeClass("active").css("width", "20");
74     }
75 </script>

 

三、活动的方法

 1 一、直接定义函数
 2 function start(){    }
 3 function end(){   }
 4 
 5 二、创建一个类
 6 function Amm(){   }
 7 
 8 Amm.prototype.start = function(){   }
 9 Amm.prototype.end = function(){    }
10 
11 
12 三、传统的程序员更喜欢把他们写到一起
13 function Amm(){  }
14 
15 Amm.prototype = {
16     start: function(){      },
17     end: function(){     }
18 }
19 
20 四、链式调用
21 window.$ = function(id){
22     return new _$(id);
23 }
24 function _$(id){
25     this.elements = document.getElementById(id);
26 }
27 _$.prototype = {
28     constructor:_$,
29     hide:function(){
30         console.log('hide');
31         return this;
32     },
33     show:function(){
34         console.log('show');
35         return this;
36     },
37     getName:function(callback){
38         if(callback){
39             callback.call(this, this.name);
40         }
41         return this;
42     },
43     setName:function(name){
44         this.name = name;
45         return this;
46     }
47 }
48 
49 $("box").setName("aa").getName(function(name){
50     console.log(name);
51 }).hide().show();

四、弱类型语言

  在js中变量不用声明其类型,不带表变量没有类型,而是变量类型取决于数据的类型,javascript的类型:整型、字符串、布尔,undefined、null

五、函数是一等对象

  函数可以存储在变量中,也可以作为参数传给另一个函数,可以作为返回值从其它函数传出,还可以进行构造,

  匿名函数,没有名字的函数,自动执行,也可以赋给一个变量  

 1 // 匿名函数
 2 (function(){
 3     var foo = 20;
 4     var bar = 10;
 5     alert(foo * bar);
 6 })();
 7 
 8 // 可加参数
 9 (function(foo, bar){
10     alert(foo * bar);
11 })(20, 10);
12 
14 // 赋给一个变量
15 var sun = (function(foo, bar){
16     return foo * bar
17 })(20, 10);
18 alert(sun);

  

  匿名函数最有趣的用途是创建“闭包”,闭包是一个受保护变量的空间,如果一个函数调变量并不想让这个变量为全局,也不是局部变量,并且让变量一直保一直保存,不会随着函数的结束而自动消毁,这样就可以使用闭包。

六、继承

  继承中不像其它面象对象语言中那么简单,js是使用基于对象的(原型式)继承

七、Javascript中使用设计模式的原因?

  1、可维护性:降低模块之间的耦合度,使代码进行重构和换用不同的模块变得容易

  2、沟通:

  3、性能:某些模式是起优化作用的可以提高运行速度,减少传送到客户端的代码量,

八、检测对象的属性和方法

1、hasOwnProperty:判断是否是对象的属性

  var obj = {};   obj.name = "haha";   obj.hasOwnProperty("haha");     // 返回true

2、constructor:查看对象是否是构造函数

 1 var type = function(o){
 2     return (o === null) ? "null" : typeof o;
 3 }
 4 
 5 var arr = new Array();
 6 
 7 if(type.constructor == Function){
 8     console.log("function");
 9 }
10 
11 if(arr.constructor == Array){
12     console.log("array");
13 }

 

3、instanceof:查看对象与构造函数之间的关系,如果对象继承过其他构造函数的方法,那就也返回真

  var arr = [];   alert(arr instanceof Array);  alert(arr instanceof Object);    // 都返回true

二、接口

一、什么是接口

  接口提供一种说明一个对象中的哪些方法

  接口的好处:能促进代码的重用,接口可以告诉程序员一个类实现了哪些方法

三、封装和信息隐藏

  为对象创建私有成员是面向对象的特性之一,目前有几种方法来创建私有、公有、特权方法的对象

  封装:通过将一个方法或者属性声明为私用的,可以让对象的实现细节对其他对象保密以降低对象之间的耦合程度,可以保持数据的完整性并对其修改方式加以约束,这样可以是代码更可靠,更易于调试。封装是面向对象的设计的基石。

  尽管JavaScript是一门面向对象的语言,可它并不具备将成员声明为公用或私用的任何内部机制,所以我们只能自己想办法实现这种特性。下面还是通过一套完整的代码去分析,介绍什么是私有属性和方法,什么是特权属性和方法,什么是属性和方法,什么是静态属性和方法。

  私有属性和方法:函数有作用域,在函数内用var 关键字声明的变量在外部无法访问,私有属性和方法本质就是你希望在对象外部无法访问的变量。

  特权属性和方法:创建属性和方法时使用的this关键字,因为这些方法定义在构造器的作用域中,所以它们可以访问到私有属性和方法;只有那些需要直接访问私有成员的方法才应该被设计为特权方法。

 1 function SetObject(name, age, sex){
 2     var _name = name;
 3     var _age = age;
 4     var _sex = sex;
 5 
 6     this.writeInfo = function(){
 7         console.log("name:" + _.name + " age:" + _.age + " sex:" + _.sex);
 8     }
 9 }
10 
11 SetObject.prototype = {
12     setInfo: function(){
13         this.writeInfo();
14     }
15 }
16 
17 var createObj = new SetObject("jack", 20, "");
18 createObj.setInfo();

  共有属性和方法:直接链在prototype上的属性和方法,不可以访问构造器内的私有成员,可以访问特权成员,子类会继承所有的共有方法。

  共有静态属性和方法:最好的理解方式就是把它想象成一个命名空间,实际上相当于把构造器作为命名空间来使用。

 1 /* -- 封装 -- */
 2 var _packaging =function(){
 3     //私有属性和方法
 4     var name ='Darren';
 5     var method1 =function(){
 6       //...
 7     }
 8     
 9     //特权属性和方法
10     this.title ='JavaScript Design Patterns' ;
11     this.getName =function(){
12       return name;
13     }
14 }
15 
16 //共有静态属性和方法
17 _packaging._name ='Darren code';
18 _packaging.alertName =function(){
19     alert(_packaging._name);
20 }
21 
22 //共有属性和方法
23 _packaging.prototype = {
24     init:function(){
25     //...
26     }
27 }

四、继承

  继承一般是在一个基础类上又增加了新的功能,但不想破坏这个基础类中的方法和属性,这样可以创建一个新的超类将基础类继承过来

  继承分为两种继承:1、继承属性  使用call来继承父类的属性    2、继承方法,使用for...in的方式将父类的方法继承过来

1、只继承属性:

 1 // 构造模式
 2 function TabB(name, age){
 3     this.name = name;
 4     this.age = age;
 5 }
 6 TabB.prototype = {
 7     sayName : function(){
 8         alert(this.name);
 9     },
10     showAge : function(){
11         alert(this.age)
12     }
13 }
14 
15 // 创建继承类
16 function CopyTabB(name, age, show){
17     TabB.call(this, name, age);
18     this.show = show;
19 }
20 
21 CopyTabB.prototype = {
22     childerName : function(){
23         console.log(this.name);
24     }
25 }
26 
27 var newTagB = new CopyTabB("虎虎", 20, true);
28 newTagB.childerName();
29 // newTagB.sayName();      // 因为没有继承父类的方法所以就会报错

2、只继承方法:有两种方式

第一种方式:CopyTabB.prototype = new TabB();    // 将子类的原型 = 创建的父类

 1 function TabB(name, age){    // 创建父类
 2     this.name = name;
 3     this.age = age;
 4 }
 5 TabB.prototype = {
 6     sayName : function(){
 7         alert(this.name);
 8     }
 9 }
10 
11 // 创建继承的子类
12 function CopyTabB(name, age, show){
13     TabB.call(this, name, age);
14     this.show = show;
15 }
16 CopyTabB.prototype = TabB.prototype;
17 // CopyTabB.prototype = new TabB();     这两种方法都是继承方法不继承属性
18 
19 var newTagB = new CopyTabB("虎虎", 20, true);
20 newTagB.sayName();

第二种方式:for...in将对象的方法循环出来

 1 // 构造模式
 2 function TabB(name, age){
 3     this.name = name;
 4     this.age = age;
 5 }
 6 TabB.prototype = {
 7     sayName : function(){
 8         alert(this.name);
 9     },
10     showAge : function(){
11         alert(this.age)
12     }
13 }
14 
15 // 创建继承类
16 function CopyTabB(name, age, show){
17     TabB.call(this, name, age);
18     this.show = show;
19 }
20 
21 extend(TabB.prototype, CopyTabB.prototype);    // 将父亲类的所有方法赋给子类
22 
23 // 将父类的方法赋给子类
24 function extend(oParent, oChilder){
25     for(var attr in oParent){
26         oChilder[attr] = oParent[attr];
27     }
28 }
29 
30 var newTagB = new CopyTabB("虎虎", 20, true);
31 newTagB.sayName();

-----------------------------------------------------------------------------------------------

继承是一个抽象的话题,继承有两种方式:1、类继承    2、原型继承

1、prototype继承

 1 // 定义一个超类
 2 function PeopleA(name){
 3     this.name = name;
 4 }
 5 
 6 // 给超类添加一个方法
 7 PeopleA.prototype.getName = function(){
 8     return this.name;
 9 }
10 
11 
12 // 在定义一个超类
13 function PeopleB(name, sex){
14     PeopleA.call(this, name);
15     this.sex = sex;
16 }
17 
18 // 类继承
19 PeopleB.prototype = new PeopleA();                 // 将new一个对象赋给prototype
20 // PeopleB.prototype = PeopleA.prototype;          // 也可以这样写
21 
22 /*
23 *  注:一定要将B类的方法写在,类继承之后,因为方法中还有调A中的属性
24 * */
25 // 给B超类添加一个方法
26 PeopleB.prototype.writeInfo = function(){
27     return this.name + this.sex;
28 }
29 
30 // 实例化话PeopleB类
31 var createPeopleB = new PeopleB("全家", 20);
32 // console.log(createPeopleB.getName());        // 如果不继承就不能使用PeopleA中的方法
33 console.log(createPeopleB.getName());
34 console.log(createPeopleB.writeInfo());

2、原型继承

 1 <script>
 2     // 创建一个超类
 3     function Person(name){
 4         this.name = name;
 5     }
 6     Person.prototype.getName = function(){
 7         return this.name;
 8     }
 9 
10     // 创建一个新类
11     function User(name, passwrod){
12         Person.call(this, name);
13         this.passwrod = passwrod;
14     }
15 User.prototype = new Person() // User对象继承Person的所有方法
    // User.prototype = Person.prototype;

16 User.prototype.getPasswrod = function(){ 17 return this.password; 18 } 19 20 var person = new User("names", 1111); 21 alert(person.getName()); 22 </script>

 

属性和方法都可以继承

 1 function Obj1(){    // 创建一个对象
 2     this.name = "siguang";
 3 }
 4 Obj1.prototype.sayName = function(){
 5     return this.name;
 6 }
 7 
 8 function Obj2(){    // 另一个对象
 9     this.age = 20;
10 }
11 
12 Obj2.prototype = new Obj1();
13 
14 var newObj = new Obj2();
15 var sName = newObj.sayName();
16 console.log(newObj.name);           // siguang
17 console.log(sName);                 // siguang

五、设计模式的类型

一、单例模式

  模块模式是为单例模式创建私有变量和特权方法,所谓的单例模式,指的就是只有一个实例的对象,javascript是以对象字面量来创建单例模式

  单例模式的用途:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

  工厂就是把成员对象的创建工作转交给一个外部对象,好处在于消除对象之间的耦合(何为耦合?就是相互影响)。通过使用工厂方法而不是new关键字及具体类,可以把所有实例化的代码都集中在一个位置,有助于创建模块化的代码,这才是工厂模式的目的和优势。

1、普通的对象字面量单例:都是公有的属性和方法

1 var obj = {
2     name : "My Object",
3     getNameFun : function(){
4        alert(this.name);
5     }
6 }
7 obj.getNameFun()

 

2、单例模式,声明的私有变量和方法

 1 var singleton = function(){
 2     // 私有变量和私有函数
 3     var privateVar = 10;
 4 
 5     // 私有函数
 6     function privateFun(){
 7         return false;
 8     }
 9 
10     // 返回对象,可以通过特权方法来访问私有属性和私有方法
11     return {
12         publicVar : 10,
13         publicMethod : function(){
14             privateVar++;
15         }
16     }
17 }
18 
19 singleton.publicMethod();

  

  单体模式之利:把方法和属性组织在一个不会被多次实例化的单体中,描述性的命名空间可以增强代码的自我说明

  单体模式之弊:单体模式提供单点访问,导致模块之间的藕和性

二、原型模式(构造函数)

  通过每个函数,都有一个prototype的属性来创造其原型方法,所有创建的对象只有一套prototype原型的方法或属性

 1 function GetObj(name, old){
 2     this.name = name;
 3     this.old = old
 4 }
 5 
 6 GetObj.prototype = {
 7     init : function(){
 8         alert(this.name + "," + this.old);
 9     }        
10 }
11 
12 var obj = new GetObj("aa", "bb");
13 obj.init();

 

普通函数与构造函数的区别

function show(){
    // var this = new object();     // 如果是new出来的会自动创建一个
    alert(this);
}

show();  // 这个时候this指向window
new show();     // 时候this指向object,如果用new出来的函数系统会自动在内部创建一个var this = new object

  

三、工厂模式

  创建一个函数,在函数内在创建一个对象并将对象返回,而不需要象构造的数一样需要new出来一个对象,因为函数返回的是一个对象所以赋给一个变量就可以直接使用

 1 function createPerson(name, age, job){
 2     var o = new Object();
 3     o.name = name;
 4     o.age = age;
 5     o.job = job;
 6     o.sayName = function(){
 7         alert(o.name);
 8     }
 9     
10     return o;
11 }
12 
13 var por = createPerson("haha", 20, "人人");
14 var join = createPerson("heihei", 30, "360");
15 console.log(por.sayName());
16 console.log(por.sayName());

1、什么时候使用工厂模式:

    1、对象的构建十分复杂    2、需要依赖具体的环境,创建不同的实例   3、处理大量具有相同的属性的小对象

  如果功能小就不适合用工厂模式,使得程序复杂

2、工厂模式存在的问题:

对象的方法都是单独存放,构造函数的原型prototype可以解决这种情况.

function createPerson(name, age){
	var obj = new Object();
	obj.name = name;
	obj.age = age;

	obj.showName = function(){
		alert(this.name);
	}
	obj.showAge = function(){
		alert(this.age);
	}
	return obj;
}

var c1 = createPerson("siguang", 30);
var c2 = createPerson("lulu", 27);
c1.showName();
c2.showName();

alert(c1.showName == c2.showName);      // 返回false,说明每次调用都会单独存放这样会占用资源,如果使用构造函数就不会存这种情况

  

四、桥接模式

  在实现API的时候桥接模式非常有用,

  桥接模式的作用在于,将抽象与实现分离,以后便二者独立变化

 1 addEevent(element, "click", getBeerById(e))
 2 
 3 function getBeerById(id, callback){
 4     var id = this.id;
 5     asyncRequest('GET', 'beer.uri?id=' + id, function(resp){
 6         // Callback response.
 7         console.log('Requested Beer: ' + resp.responseText);
 8     })
 9 }
10 
11 function asyncRequest(type, data, callback){}

// 方法的链式调用 

  把方法串链起来调用,象Jquery一样,$("#name").find("span").addClass("active");

  这种技术分为两部分:1、创建代表HTML元素的工厂(工厂模式)  2、  

  

// 使用单例模式和构造函数的区别

 1 <script>
 2     // 使用对象直接量(单体模式)和构造函数的区别
 3     // 对象直接量
 4     var Obj = {
 5         getName: "10",
 6 
 7         selectName: function(){
 8             alert(this.getName);
 9             this.getName+=10;
10         }
11     }
12 
13     $("#btn1").click(function(){
14         Obj.selectName();           // 每点击一次getName都累加10
15     })
16 
17     $("#btn2").click(function(){
18         Obj.selectName();           // 每点击一次getName都累加10
19     })
20 
21     
22     // 构造函数
23     function Obj(){
24         this.getName = 10;
25     }
26 
27     Obj.prototype.selectName = function(){
28         alert(this.getName);
29         this.getName+=10;
30     }
31 
32     var n1 = new Obj();
33     var n2 = new Obj();
34     $("#btn1").click(function(){
35         n1.selectName();                // 每点击一次n1下的getName都会加10
36     })
37 
38     $("#btn2").click(function(){
39         n2.selectName();                // 每点击一次n2下的getName都会加10
40     })
41 </script>

六、模块化

模块方式一

 1 var singleton = function(){
 2     // 私有属性
 3     var parive = 0;
 4     
 5     // 私有方法
 6     function getParive(){
 7         console.log(parive);
 8     }
 9 
10     function getName(){
11         console.log("siguang");
12     }
13 
14     return {
15         getParive: getParive(),
16         getName  : getName()
17     }
18 }()
19 
20 singleton.getParive;        // 调用

模块方法二:

 1 (function(){
 2     var name = "siguang";
 3 
 4     function Person(val){
 5         this.name = val;
 6     }
 7 
 8     Person.prototype.getName = function(){
 9         console.log(this.name);
10     }
11 
12     var newObj = new Person(name);
13     newObj.getName();
14 })()

JS的压缩器

  分发js库的一个不可缺少的方面是压缩来节省带宽,有三种类型的压缩器:

  1、简单的删除空格和换行和注释,公保留主要的代码

  2、删除空白注释,也同将所有的变量名变得改短的压缩

  3、删除空白和注释,同时还最小化代码中的所有单词(不仅是变量名)的压缩器

  两种不同的库:JSMin和Paker

  JSMin:删除无关的非代码  Paker:属于第三类彻底压缩所有单词

原文地址:https://www.cnblogs.com/couxiaozi1983/p/3275383.html