JavaScript品质优化

JavaScript的性训斥题不容轻渎,那就必要大家开辟职员在编辑JavaScript程序时多留意一些细节,本文特别详细的牵线了一下JavaScript品质优化地方的知识点,相对是干货。

前言

向来在上学javascript,也许有看过《犀利开荒Jquery内核安详严整与施行》,对那本书的评说独有七个字犀利,恐怕是对javascript明白的还远远不足通透到底异或是本身太笨,越多的是自个儿不擅于考虑懒得构思以至于里面说的风流罗曼蒂克对精美利坚合众国的首都还未太深入的知情。

鉴于想让投机有三个升格,进不了二个越来越普及的天地,总得找八个归于本身的宅集散地好好活着,所以平日会顺手的去储存一些采纳jQuerry的常用知识,极度是对此品质必要这一块,总是会想是还是不是有更加好的法门来落到实处。

下边是自身计算的局地小技艺,仅供仿照效法。(笔者先会说一个总题目,然后用一小段话来证实这些意思
再最终用二个demo来简单言明卡塔尔国

幸免全局查找

在三个函数中会用到全局对象存款和储蓄为一些变量来收缩全局查找,因为访问些变量的快慢要比访谈全局变量的快慢更加快些

        function search() {
            //当我要使用当前页面地址和主机域名
            alert(window.location.href + window.location.host);
        }
        //最好的方式是如下这样  先用一个简单变量保存起来
        function search() {
            var location = window.location;
            alert(location.href + location.host);
        }

定时器

生机勃勃旦针没有错是不断运行的代码,不应有运用setTimeout,而应该是用setInterval,因为setTimeout每二遍都会开头化二个计时器,而setInterval只会在最早的时候早先化二个电火花计时器

        var timeoutTimes = 0;
        function timeout() {
            timeoutTimes++;
            if (timeoutTimes < 10) {
                setTimeout(timeout, 10);
            }
        }
        timeout();
        //可以替换为:
        var intervalTimes = 0;
        function interval() {
            intervalTimes++;
            if (intervalTimes >= 10) {
                clearInterval(interv);
            }
        }
        var interv = setInterval(interval, 10);

字符串连接

只要要一连多少个字符串,应该少使用+=,如

s+=a;

s+=b;

s+=c;

相应写成s+=a + b + c;

而假如是收集字符串,比如数次对同二个字符串进行+=操作的话,最佳使用二个缓存,使用JavaScript数组来搜集,最终动用join方法连接起来

        var buf = [];
        for (var i = 0; i < 100; i++) {
            buf.push(i.toString());
        }
        var all = buf.join("");

避免with语句

和函数肖似,with语句会创制本人的功能域,因而会追加之中执行的代码的机能域链的长短,由于额外的效能域链的搜索,在with语句中施行的代码肯定会比外面实施的代码要慢,在能不行使with语句的时候尽量不要采纳with语句

 with (a.b.c.d) {
            property1 = 1;
            property2 = 2;
        }
        //可以替换为:
        var obj = a.b.c.d;
        obj.property1 = 1;
        obj.property2 = 2;

数字调换来字符串

般最佳用”” +
1来将数字转变来字符串,尽管看起来极难看一点,但实际上这么些频率是最高的,性能上来讲:

(“” +) > String() > .toString() > new String()

浮点数转变到整型

多多人喜好使用parseInt(卡塔尔,其实parseInt(卡塔尔(قطر‎是用来将字符串调换来数字,并不是浮点数和整型之间的调换,大家应该运用Math.floor(State of Qatar恐怕Math.round(卡塔尔

各种类型转换

var myVar = "3.14159",
        str = "" + myVar, //  to string  
        i_int = ~ ~myVar,  //  to integer  
        f_float = 1 * myVar,  //  to float  
        b_bool = !!myVar,  /*  to boolean - any string with length 
                                and any number except 0 are true */
        array = [myVar];  //  to array

假设定义了toString(卡塔尔方法来扩充类型转变的话,推荐显式调用toString(卡塔尔,因为个中的操作在品味全部望之后,会尝试对象的toString(卡塔尔方法尝试是还是不是转正为String,所以直接调用这些法子功用会更加高

多个项目申明

在JavaScript中持有变量都得以运用单个var语句来声称,那样便是构成在联合的讲话,以减少整个脚本的实行时间,就像下面代码相近,上边代码格式也挺正式,令人风度翩翩看就明了。

布置迭代器

如var name=values[i]; i++;前边两条语句能够写成var name=values[i++]

动用间接量

var aTest = new Array(); //替换为
        var aTest = [];
        var aTest = new Object; //替换为
        var aTest = {};
        var reg = new RegExp(); //替换为
        var reg = /../;
        //如果要创建具有一些特性的一般对象,也可以使用字面量,如下:
        var oFruit = new O;
        oFruit.color = "red";
        oFruit.name = "apple";
        //前面的代码可用对象字面量来改写成这样:
        var oFruit = { color: "red", name: "apple" };

应用DocumentFragment优化多次append

如果需求创新DOM,请思索接受文书档案碎片来创设DOM布局,然后再将其增加到现成的文书档案中。

for (var i = 0; i < 1000; i++) {
            var el = document.createElement('p');
            el.innerHTML = i;
            document.body.appendChild(el);
        }
        //可以替换为:
        var frag = document.createDocumentFragment();
        for (var i = 0; i < 1000; i++) {
            var el = document.createElement('p');
            el.innerHTML = i;
            frag.appendChild(el);
        }
        document.body.appendChild(frag);

行使三遍innerHTML赋值代替营造dom成分

对此大的DOM改正,使用innerHTML要比使用专门的学问的DOM方法创立相近的DOM结构快得多。

        var frag = document.createDocumentFragment();
        for (var i = 0; i < 1000; i++) {
            var el = document.createElement('p');
            el.innerHTML = i;
            frag.appendChild(el);
        }
        document.body.appendChild(frag);
        //可以替换为:
        var html = [];
        for (var i = 0; i < 1000; i++) {
            html.push('<p>' + i + '</p>');
        }
        document.body.innerHTML = html.join('');

经过沙盘成分clone,替代createElement

不少人欢快在JavaScript中使用document.write来给页面生成内容。事实上那样的效用超低,要是要求直接插入HTML,能够找一个容器成分,比方钦点一个div可能span,并安装他们的innerHTML来将和睦的HTML代码插入到页面中。平日大家大概会利用字符串间接写HTML来创设节点,其实这么做,1不能确定保证代码的得力2字符串操作效用低,所以应该是用document.createElement(卡塔尔(قطر‎方法,而生机勃勃旦文书档案中设有现存的规范节点,应该是用cloneNode(卡塔尔(قطر‎方法,因为运用createElement(卡塔尔(قطر‎方法之后,你供给安装多次成分的习性,使用cloneNode(卡塔尔(قطر‎则能够减削属性的装置次数——雷同要是急需创建超多因素,应该先准备贰个范例节点

        var frag = document.createDocumentFragment();
        for (var i = 0; i < 1000; i++) {
            var el = document.createElement('p');
            el.innerHTML = i;
            frag.appendChild(el);
        }
        document.body.appendChild(frag);
        //替换为:
        var frag = document.createDocumentFragment();
        var pEl = document.getElementsByTagName('p')[0];
        for (var i = 0; i < 1000; i++) {
            var el = pEl.cloneNode(false);
            el.innerHTML = i;
            frag.appendChild(el);
        }
        document.body.appendChild(frag);

使用firstChild和nextSibling代替childNodes遍历dom元素

图片 1

        var nodes = element.childNodes;
        for (var i = 0, l = nodes.length; i < l; i++) {
            var node = nodes[i];
            //……
        }
        //可以替换为:
        var node = element.firstChild;
        while (node) {
            //……
            node = node.nextSibling;

删除DOM节点

剔除dom节点在此以前,必须要刨除注册在该节点上的平地风波,不管是用observe方式依然用attachEvent情势注册的平地风波,不然将会生出无法回笼的内存。其余,在removeChild和innerHTML=’’二者之间,尽量筛选后面一个.
因为在sIEve(内部存款和储蓄器泄露监测工具卡塔尔(قطر‎中监测的结果是用removeChild不能够有效地放走dom节点

接收事件代理

别的能够冒泡的事件都不只好在事变目的上海展览中心开始拍戏卖,指标的其他祖先节点上也能管理,使用那几个知识就足以将事件管理程序附加到越来越高之处担负八个对象的事件管理,相通,对于内容动态扩充并且子节点都亟需风度翩翩致的事件管理函数的状态,能够把事件注册涉嫌父节点上,那样就不须求为各样子节点注册事件监听了。此外,现存的js库都接收observe情势来创制事件监听,其落到实处上隔断了dom对象和事件管理函数之间的循环引用,所以应该尽只怕利用这种措施来创立事件监听

重复使用的调用结果,事情发生前保存到一些变量

        //避免多次取值的调用开销
        var h1 = element1.clientHeight + num1;
        var h2 = element1.clientHeight + num2;
        //可以替换为:
        var eleHeight = element1.clientHeight;
        var h1 = eleHeight + num1;
        var h2 = eleHeight + num2;

注意NodeList

最小化访谈NodeList的次数能够十分的大的修正脚本的品质

        var images = document.getElementsByTagName('img');
        for (var i = 0, len = images.length; i < len; i++) {

        }

编排JavaScript的时候明显要精通几时回到NodeList对象,这样能够最小化对它们的拜见

  • 進展了对getElementsByTagName(卡塔尔的调用
  • 收获了成分的childNodes属性
  • 拿到了成分的attributes属性
  • 做客了超过常规规的集纳,如document.forms、document.images等等

要明白了当使用NodeList对象时,合理运用会超级大的晋升代码实施速度

优化循环

能够动用下边二种艺术来优化循环

  • 减值迭代

大部周而复始利用三个从0开头、增到有个别特定值的迭代器,在好些个情状下,从最大值初始,在循环中连连减值的迭代器特别火速

  • 简化终止条件

出于每便循环进度都会精兵简政终止条件,所以必得保险它尽也许快,约等于说幸免属性查找或然别的的操作,最佳是将循环调节量保存到一些变量中,也正是说对数组或列表对象的遍历时,提前将length保存到有个别变量中,防止在循环的每一步重复取值。

        var list = document.getElementsByTagName('p');
        for (var i = 0; i < list.length; i++) {
            //……
        }

        //替换为:
        var list = document.getElementsByTagName('p');
        for (var i = 0, l = list.length; i < l; i++) {
            //……
        }
  • 简化循环体

循环体是实行最多的,所以要保险其被最大限度的优化

  • 行使后测量检验循环

在JavaScript中,大家能够动用for(;;卡塔尔(قطر‎,while(State of Qatar,for(inState of Qatar两种循环,事实上,那三种循环中for(in卡塔尔的频率极差,因为她索要查询散列键,只要能够,就应有尽量少用。for(;;State of Qatar和while循环,while循环的成效要降价for(;;卡塔尔国,或许是因为for(;;卡塔尔国结构的标题,必要日常跳转回来。

        var arr = [1, 2, 3, 4, 5, 6, 7];
        var sum = 0;
        for (var i = 0, l = arr.length; i < l; i++) {
            sum += arr[i];
        }

        //可以考虑替换为:

        var arr = [1, 2, 3, 4, 5, 6, 7];
        var sum = 0, l = arr.length;
        while (l--) {
            sum += arr[l];
        }

最常用的for循环和while循环都早先测量试验循环,而如do-while这种后测量检验循环,能够幸免中期终止条件的总结,因而运营更加快。

打开循环

当循环次数是规定的,毁灭循环并行使频仍函数调用往往会更加快。

幸免重新解释

假设要加强代码品质,尽大概制止现身供给服从JavaScript解释的字符串,也正是

  • 尽量少使用eval函数

选用eval约等于在运营时再一次调用解释引擎对剧情开展运作,供给开销多量小时,何况使用Eval带给的安全性难点也是小心的。

  • 绝不使用Function布局器

无须给setTimeout也许setInterval传递字符串参数

        var num = 0;
        setTimeout('num++', 10);
        //可以替换为:
        var num = 0;
        function addNum() {
            num++;
        }
        setTimeout(addNum, 10);

浓缩否定检查实验

       if (oTest != '#ff0000') {
            //do something
        }
        if (oTest != null) {
            //do something
        }
        if (oTest != false) {
            //do something
        }
        //虽然这些都正确,但用逻辑非操作符来操作也有同样的效果:
        if (!oTest) {
            //do something
        }

条件分支

  • 将标准分支,按也许性顺序从高到低排列:能够减削解释器对标准的探测次数
  • 在同一条件子的多(>2)条件分支时,使用switch优于if:switch分支选拔的效能超越if,在IE下尤为刚强。4分段的测量试验,IE下switch的试行时间约为if的四分之二。
  • 采取三目运算符替代条件分支

        if (a > b) {
            num = a;
        } else {
            num = b;
        }
        //可以替换为:
        num = a > b ? a : b;
    

动用常量

  • 重复值:任何在多处用到的值都应该抽出为二个常量
  • 客户分界面字符串:任何用于体现给顾客的字符串,都应有抽出出来以便于国际化
  • URLs:在Web应用中,财富任务非常轻易更改,所以推举用三个共用地方寄放全数的UPAJEROL
  • 随意恐怕会更正的值:每当你用到字面量值的时候,你都要问一下本身那么些值在现在是否会扭转,倘诺答案是“是”,那么那一个值就应该被提抽出来作为一个常量。

制止与null进行相比较

出于JavaScript是弱类型的,所以它不会做别的的自动类型检查,所以若是见到与null实行相比的代码,尝试利用以下本领替换

  • 大器晚成旦值应该为三个援用类型,使用instanceof操作符检查其布局函数
  • 若是值应该为叁个为主类型,成效typeof检查其品种
  • 假如是梦想对象蕴含有些特定的法门名,则采用typeof操作符确定保障钦定名字的章程存在于对象上

制止全局量

全局变量应该全套字母大写,各单词之间用_下划线来连接。尽或者避免全局变量和函数,
尽量收缩全局变量的利用,因为在叁个页面中蕴藏的持有JavaScript都在同叁个域中运维。所以假设您的代码中扬言了全局变量只怕全局函数的话,后边的代码中载入的本子文件中的同名变量和函数会覆盖掉(overwrite)你的。

//糟糕的全局变量和全局函数
var current = null;
function init(){
//...
}
function change() {
    //...
}
function verify() {
    //...
}
//解决办法有很多,Christian Heilmann建议的方法是:
//如果变量和函数不需要在“外面”引用,那么就可以使用一个没有名字的方法将他们全都包起来。
(function(){
var current = null;
function init() {
    //...
}
function change() {
    //...
}
function verify() {
    //...
}
})();
//如果变量和函数需要在“外面”引用,需要把你的变量和函数放在一个“命名空间”中
//我们这里用一个function做命名空间而不是一个var,因为在前者中声明function更简单,而且能保护隐私数据
myNameSpace = function() {
    var current = null;

    function init() {
        //...
    }

    function change() {
        //...
    }

    function verify() {
        //...
    }

//所有需要在命名空间外调用的函数和属性都要写在return里面
    return {
        init: init,
        //甚至你可以为函数和属性命名一个别名
        set: change
    };
};

重申对象的全部权

因为JavaScript能够在别的时候修正任性对象,这样就能够以不足预测的主意覆写暗中认可的一颦一笑,所以后生可畏旦你不担任敬性格很顽强在荆棘塞途或巨大压力面前不屈有些对象,它的目的只怕它的艺术,那么你就毫无对它进行改换,具体一点正是说:

  • 永不为实例或原型加多属性
  • 并非为实例恐怕原型增添方法
  • 不要重定义已经存在的点子
  • 毫不再一次定义其余组织成员已经实现的情势,永世不要涂改不是由你有着的指标,你能够由此以下情势为对象创制新的据守:
  • 创办包涵所需功效的新指标,并用它与有关对象举办相互作用
  • 创制自定义类型,世袭需求开展校订的项目,然后可感到自定义类型增添额外功能

巡回援用

若是循环引用中包蕴DOM对象只怕ActiveX对象,那么就能发出内存泄露。内部存款和储蓄器走漏的结果是在浏览器关闭前,尽管是刷新页面,那有个别内存不会被浏览器释放。

粗略的轮回引用:

        var el = document.getElementById('MyElement');
        var func = function () {
            //…
        }
        el.func = func;
        func.element = el;

可是普通不会现出这种景况。平时循环引用发生在为dom成分增加闭包作为expendo的时候。

        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
        }
        init();

init在推行的时候,当前上下文大家誉为context。那时候,context引用了el,el征引了function,function援引了context。那时形成了二个循环援用。

下边2种艺术能够解决循环引用:

1)  置空dom对象

       function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
        }
        init();
        //可以替换为:
        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
            el = null;
        }
        init();

将el置空,context中不含有对dom对象的援引,进而打断循环利用。

生机勃勃经大家必要将dom对象回来,可以用如下方法:

        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
            return el;
        }
        init();
        //可以替换为:
        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
            try {
                return el;
            } finally {
                el = null;
            }
        }
        init();

2卡塔尔国  构造新的context

        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
        }
        init();
        //可以替换为:
        function elClickHandler() {
            //……
        }
        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = elClickHandler;
        }
        init();

把function抽到新的context中,那样,function的context就不带有对el的援用,进而打断循环援用。

通过javascript创立的dom对象,必须append到页面中

IE下,脚本创设的dom对象,若无append到页面中,刷新页面,这有的内存是不会回笼的!

        function create() {
            var gc = document.getElementById('GC');
            for (var i = 0; i < 5000; i++) {
                var el = document.createElement('div');
                el.innerHTML = "test";
                //下面这句可以注释掉,看看浏览器在任务管理器中,点击按钮然后刷新后的内存变化
                gc.appendChild(el);
            }
        }

刑释dom成分占用的内部存储器

将dom成分的innerHTML设置为空字符串,能够释放其子成分占用的内部存款和储蓄器。

在rich应用中,客商大概会在一个页面上驻留很短日子,能够动用该措施释放积存得更为多的dom成分运用的内部存款和储蓄器。

释放javascript对象

在rich应用中,随着实例化对象数量的增加,内部存款和储蓄器消耗会愈加大。所以应当立即放出对目的的援引,让GC可以回笼那么些内部存款和储蓄器控件。

对象:obj = null

对象属性:delete obj.myproperty

数组item:使用数组的splice方法释放数组中并非的item

制止string的隐式装箱

对string的办法调用,比方’xxx’.length,浏览器博览会开二个隐式的装箱操作,将字符串先调换来三个String对象。推荐对证明有望采用String实例方法的字符串时,接受如下写法:

var myString = new String(‘Hello
World’);

麻痹大要耦合

1、解耦HTML/JavaScript

JavaScript和HTML的牢牢耦合:直接写在HTML中的JavaScript、使用带有内联代码的<script>成分、使用HTML属性来分配事件管理程序等

HTML和JavaScript的牢牢耦合:JavaScript中带有HTML,然后使用innerHTML来插入生机勃勃段html文本到页面

骨子里应该是维系档次的辞行,那样能够十分轻便的规定错误的来自,所以大家应保障HTML显示应该尽恐怕与JavaScript保持分离

2、解耦CSS/JavaScript

展现难题的唯一来源应该是CSS,行为难点的天下无双来源应该是JavaScript,档案的次序之间保持松散耦合才得以让您的应用程序尤其便于维护,所以像以下的代码element.style.color=”red”尽量改为element.className=”edit”,何况不要在css中经过表明式嵌入JavaScript

3、解耦应用程序/事件管理程序

将应用逻辑和事件管理程序相抽离:八个事件管理程序应该从事件指标中领取,并将这一个新闻传送给管理应用逻辑的有些方法中。那样做的益处首先能够让您更便于改进触发特定进程的事件,其次能够在不附加事件的场合下测量试验代码,使其更易创造单元测量试验

质量方面的注意事项

1、尽量选择原生方法

2、switch语句相对if非常快

通过将case语句根据最大概到最不或许的生机勃勃生龙活虎举行集体

3、位运算异常快

当实行数字运算时,位运算操作要比其他布尔运算或然算数运算快

**4、巧用||和&&布尔运算符**

        function eventHandler(e) {
            if (!e) e = window.event;
        }
        //可以替换为:
        function eventHandler(e) {
            e = e || window.event;
        }

        if (myobj) {
            doSomething(myobj);
        }
        //可以替换为:
        myobj && doSomething(myobj);

制止不当应注意的地点

1、每条语句末尾须加分号

在if语句中,尽管条件表明式唯有一条语句也要用{}把它括起来,避防持续固然增添了讲话之后引致逻辑错误

2、使用+号时需谨严

JavaScript 和其它编制程序语言分歧的是,在 JavaScript
中,’+’除了表示数字值相加,字符串相连接以外,还足以作一元运算符用,把字符串转变为数字。因此假诺使用不当,则大概与自增符’++’混淆而孳生计算错误

        var valueA = 20;
        var valueB = "10";
        alert(valueA + valueB);     //ouput: 2010 
        alert(valueA + (+valueB));  //output: 30 
        alert(valueA + +valueB);    //output:30 
        alert(valueA ++ valueB);     //Compile error

3、使用return语句要求潜心

一条有再次来到值的return语句并不是用(卡塔尔括号来括住重临值,固然回去表明式,则表达式应与return关键字在一直以来行,以制止压缩时,压缩工具自动加分号而招致再次来到与开荒人士不平等的结果

        function F1() {
            var valueA = 1;
            var valueB = 2;
            return valueA + valueB;
        }
        function F2() {
            var valueA = 1;
            var valueB = 2;
            return
            valueA + valueB;
        }
        alert(F1());  //output: 3 
        alert(F2());  //ouput: undefined

==和===的区别

制止在if和while语句的原则部分实行赋值,如if (a = b卡塔尔国,应该写成if (a ==
bState of Qatar,可是在可比是或不是等于的图景下,最棒使用全等运转符,相当于使用===和!==操作符会相对于==和!=会好点。==和!=操作符会进行项目强逼调换

        var valueA = "1";
        var valueB = 1;
        if (valueA == valueB) {
            alert("Equal");
        }
        else {
            alert("Not equal");
        }
        //output: "Equal"
        if (valueA === valueB) {
            alert("Equal");
        }
        else {
            alert("Not equal");
        }
        //output: "Not equal"

永不选择生偏语法

无须接受生偏语法,写令人吸引的代码,即使Computer能够正确识别并运转,可是晦涩难懂的代码不便于现在维护

函数重返统风流罗曼蒂克类型

纵然JavaScript是弱类型的,对于函数来讲,后面重回整数型数据,前边重回布尔值在编写翻译和周转都能够寻常通过,但为了标准和后来维护时便于掌握,应保障函数应重返统生机勃勃的数据类型

总是检查数据类型

要反省你的形式输入的装有数据,一方面是为了安全性,其他方面也是为了可用性。客户任何时间任何地方都会输入错误的数据。那不是因为她们蠢,而是因为她们很忙,何况观念的点子跟你区别。用typeof方法来检查测验你的function接纳的输入是还是不是合法

几时用单引号,几时用双引号

尽管如此在JavaScript个中,双引号和单引号都足以表示字符串,
为了幸免混乱,大家建议在HTML中央银行使双引号,在JavaScript中动用单引号,但为了合作各类浏览器,也为理解析时不会出错,定义JSON对象时,最棒使用双引号

部署

  • 用JSLint运维JavaScript验证器来保管未有语法错误可能是代码没有地下的问
  • 安顿此前推荐应用压缩工具将JS文件收缩
  • 文本编码统大器晚成用UTF-8
  • JavaScript 程序应该尽恐怕放在 .js 的文书中,供给调用的时候在 HTML 中以
    <script src=”filename.js”> 的款型满含进来。JavaScript
    代码若不是该 HTML 文件所专项使用的,则应尽量防止在 HTML 文件中一直编写
    JavaScript 代码。因为这么会大大扩张 HTML
    文件的朗朗上口,无益于代码的裁减和缓存的选取。其余,<script
    src=”filename.js”>
    标签应竭尽放在文件的后边,最棒是坐落于</body>标签前。那样会减低因加载
    JavaScript 代码而影响页面中其余组件的加载时间。

长久不要忽略代码优化专门的学问,重构是黄金年代项从品种上马到截至必要持续的办事,独有时时刻刻的优化代码技能让代码的实践功效进一层好

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website