第四章 语言模块

1.字符串的扩展与修复

语言脚本都对字符串特别关注,有关的方法特别多,这些方法有三大类:

第一类:与标签无关的实现:charAt,charCodeAt,concat,lastIndexOf,localeCompare,match,replace,slice,split,substr,substring,toLocaleLowerCase,toLocalUpperCase,toLowerCase,toUpperCase以及从Object继承来的方法。如,toString,valueOf

第二类:与标签有关的实现,都是对原字符串添加的一对标签:anchor,big,blink,blod,fixed,fontcolor,italics,link,small,strike,sub,sup

第三类是后来添加或未标准化的浏览器方法,如trim,quote,toSource,trimLeft,trimRight.其中,trim已经标准化,后四个是FF的私有实现。

先看看prototypejs添加的扩展,

gsub,sub,scan,truncate,strip,stripTags,stripScript,extractScripts,evalScripts,escapeHYML,unescapeHTML,parseQuery,toArray,succ,times,camelize,capitalize,underscore,dasherize,inspect,unfliterJSON,isJSON,evalJSON,include,starsWith,endsWith, empty,blank,interpolate。

其中,gsub,sub,scan与正则相关,直接取ruby的命名

truncate是字符串截取,非常有用

strip即trim,已标准化

stripTags去掉字符串的标签对,非常有用。

stripScript是单单把script标签去掉,露出script.text

escapeHTML与unescapeHTML是用户输入输出的操作定义,非常有用。

parseQuery基本是对url的search部分的操作。

inspect就是在两端加双引号,用于构建json。

empty和blank是对空白进行判定,很简单的方法。

prototype.js这些框架经常被其它框架抄去,看抄去的功能,我们就知道哪些方法有价值。

rightJs的字符串扩展:include , black , camelize , capitalize , dasherize , empty, endsWith,evalScripts , extarctScripts, includes, on , startsWidth , stripScripts, stripTags, toFlaot, toInt, trim , underscored

Mootools的字符扩展(原型扩展) test, contains , trim , clean , camelCase, hyphenate , capitalize , escapeRegExp , toInt , toFloat , hexToRgb, rgbToHex , substitute , stripScripts

dojo的字符串扩展, rep , pad , substitute , trim , rep就是repeat方法

Ext字符串扩展,capitalize , ellipsis , escape , escapeRegex format htmlDecode, htmlEncode leftPad, parseQueryString , trim , urlAppend

百度七巧板的字符扩展有:decodeHTML ,encodeHTML , escapeReg , filterFormat , format, formatColor , stripTags , toCamelCase, toHalfWidth , trim , wbr

下面举例实现方法:

contains方法:判定一个字符串是否包含另一个字符串。常规思维,使用正则,但每次都要用new RegExp来构造,太麻烦,性能太差。转而使用原生字符串方法。如indexOf , lastIdexOf , search

    function contains (target, it) {
        return target.lastIndexOf(it) != -1; //indexOf改成search, lastIndexOf也可以
    }

在mootools版中,我们看到它支持更多的参数,目的是判定一个元素的className是否包含某个特定的class。众所周知,元素可以添加多个class,中间以空格隔开,使用mootoos的contains就很方便检测包含关系了。

    function contains (target, str, separator) {
        return separator ? ( separator + target + separator).indexOf(separator + str +separator) > -1 : target.indexOf(str) > -1;
    }

repeat方法: 将一个字符串重复n次,如repeat("ruby",2)得到rubyruby

版本1:利用空数组的join方法

    function repeat (target, n) {
        return (new Array(n + 1)).join(target);
    }

版本2.....6...

版本7,递归在浏览器下做了优化 ,包括ie6,属于最好的实现方式之一

    function repeat (target, n) {
        if (n == 1){
            return target
        }
        var s = repeat(target, Math.floor(n/2));
        s += s;
        if (n % 2) {
            s += target;
        }
        return s;
    }

byteLen方法:取得一个字符串所有字节的长度。这是一个后端转过来的方法。在前端,我们要用户填写文本,需要字节有限制。

版本1:假设字符每个字符Unicode编码小于等于255,byteLength为字符串长度。再遍历字符串,遇到unicode编码大于255时,为byteLength加1

function byteLen (target) {
        var byteLength = target.length,
            i = 0;
        for ( ; i < target.length ; i++) {
            if (target.charCodeAt(i) > 255) {
                byteLength++;
            }
        }
        return byteLength;
    }

truncate方法,用于对字符串进行截断处理,当超过限定长度,默认添加三个点号等

    function truncate (target, length , truncation) {
        length = length || 30;
        truncation = truncation === void(0) ? ‘...‘ : truncation;
        return target.length > length ? target.slice(0, length - truncation.length) + truncation : String(target);
    }

camelize方法,转换为驼峰命名风格

    function camelize (target) {
        if (target.indexOf(‘_‘) < 0 && target.indexOf(‘_‘) < 0) {
            return target; //提前判断,提高响应效率
        }
        return target.replace(/[-_][^-_]/g , function(match){
            return match.charCodeAt(1).toUpperCase();
        })
    }

underscored方法。转换为下划线风格

function underscored(target){
        return target.replace(/([a-z\d])([A-Z])/g , ‘$1_$2‘).replace(/\-/g , ‘_‘).toLowerCase();
    }

dasherize方法,转换为连字符风格,亦指css变量风格(承上面的方法)

    function dasherize(target){
        return underscored(target).replace(/_/g, ‘-‘);
    }

capitalize方法,首字母大写

    function capitalize(target) {
        return target.charAt(0).toUpperCase() + target.substring(1).toLowerCase();
    }

stripTags方法,移除字符中的html标签。但有一个缺陷,如果其中有script标签,会把不该显示的脚本也显示出来。

    function stripTags(target){
        return String(target || "") .replace(/<[^>]+>/g, ‘‘);
    }

escapeHTML和unescapeHTML略

escapeRegExp方法:将字符串安全格式转换为正则表达式的源码

    function escapeRegExp(target){
        return target.replace(/([-.*+?^${}()|[\]\/\\])/g, ‘\\$1‘);
    }

 pad方法,与trim方法相反,pad可以为字符串的某一端添加字符串。常见的是在日历的月份前面加补0,因此,被称为fillZero

    function pad(target,n){
        var zero = new Array(n).join(‘0‘);
        var str = zero + target;
        var resulet = str.substr(-n);
        return resulet;
    }

高级方法,也是mass Framework使用的版本,支持更多的参数。允许从左边或从右填充。以及使用什么内容进行填充。

    function pad (target, n, filling, right, radix){
        var num = target.toString(radix || 10);
        filling = filling || "0";
        while (num.length < n){
            if(!right){
                num = filling + num;
            } else {
                num += filling;
            }
            return num;
        }
    }

wbr方法,为目标字符串添加wbr换行。不过需要注意的是,它不是为每个字符串都插入<wbr>字样,而是相当于在组成文本节点的报语法中的每个字符后插入<wbr>字样。如果是aa<span>bb</span>cc,返回a<wbr>a<span>b<wbr>b</span>c<wbr>c<wbr>,在opear浏览器上,默认的css不会添加上wbr样式,需要在css上添加,wbr:after{content:"\00200B"}解决此问题

    function wbr (target){
        return String(target).replace(/(?:<[^>]+>) | (?:&#?[0-9a-z]{2,6};) | (.{1})/gi,‘$&<wbr>‘).replace(/><wbr>/g,‘>‘);
    }

format方法,在c语言中,有一个printf方法,我们可以在后面添加不同的类型的参数嵌入到将要输出的字符串中。这是非常有用的方法,因为在javascript中涉及到大量这样字符串拼接的工作 ,如果涉及逻辑,我们可以用模板,如果轻量点,我们可以用这个方法。

在不同的框架中名字不同,prototype.js 叫interpolate,Base2叫format,mootools叫substitute

    function format (str, object){
        var array = Array.prototype.slice.call(arguments, 1);
        return str.replace(/\\?\#{([^{}]+)\}/gm,function(match, name) {
            if(match.charAt(0) == ‘\\‘)
                return match.slice(1);
            var index = Number(name)
            if(index >= 0)
                return array[index];
            if (object && object[name] !== void 0)
                return object[name];
            return ‘‘;
        });
    }
    var a = format("resulet is #{0}, #{1}",22,33)
    console.log(a) // resulet is 22, 33
    var b = format ( "#{name} is a #{sex} #{am}" ,{
        name:"wangjie",
        sex:"man",
        am:"111"
    });
    console.log(b) // wangjie is a man 111

它支持两种传参方法,如果字符串的占位符为0,1,2这样的非零整数,要求传入两个或以上的参数,否则就传入一个对象,键名为占位符。

quote方法,在字符串的两端加上双引号。然后内部需要转义的地方都要转义。用于接装JSON的键名或模析系统中

    //code.google.com/jQuery-json
    var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g,
                    meta = {
                        ‘\b‘:‘\\b‘,
                        ‘\t‘:‘\\t‘,
                        ‘\n‘:‘\\n‘,
                        ‘\f‘:‘\\f‘,
                        ‘\r‘:‘\\r‘,
                        ‘"‘:‘\\"‘,
                        ‘\\‘:‘\\\\‘
                    };
    function quote(target){
        if (target.match(escapeable)){
            return ‘"‘ + target.replace(escapeable,function(a) {
                var c = meta[a];
                if(typeof c === ‘string‘) {
                    return c;
                }
                return ‘\\u‘ + (‘0000‘ + c.charCodeAt(0).toString(16)).slice(-4)
            }) + ‘"‘;
        }
        return ‘"‘ + target + ‘"‘;
    }               

当然,如果浏览器支持原生的JSON,我们直接用JSON.stringify就行了,另外,FF在JSON发明之前,就支持String.prototype.quote与String.quote方法了,我们使用quote之前判定浏览器是否内置这些方法

字符串好像没有打的浏览器兼容问题,有的话是IE6,IE7不支持用数组中括号取它的每一个字符,需要用charAt来取。IE678不支持垂直分表符,因此有如下hack

var isIe678 = !+"\v1";

修复旧版本IE中的trim函数。这是一个很常用的操作,通常我们需要把表单的两侧空白清除掉

版本1,用了两次正则,实际速度非常惊人,主要得益于浏览器的内部优化。base2使用这种优化,引起了其它浏览器的跟风。于是正则的实现再也比不过字符串方法了。一个著名的例子,字符串拼接。直接相加比Array做成的StringBuffer还快。而StringBuffer技术在早些年备受推崇。

    function trim(str){
        return str.replace(/^\s\s*/, ‘‘).replace(/\s\s*$/, ‘‘);
    }

版本2

利用两个候选操作符链接两个正则,这样做就失去了浏览器优化的机会。由于看起来很优雅,很多类库都使用它。如jQuery,mootools

    function trim(str){
        return str.replace(/^\s+|\s+$/g, ‘‘);
    }

版本3

更好的改进版

    function trim(str){
        var str = str.replace(/^\s\s*/, ""),
                ws = /\s/,
                i = str.length;
    while (ws.test(str.charAt(--i)))
        return str.slice(0, i + 1);
    }

2.数组的扩展与修复

得益于Prototype.js的ruby式数组方法的侵略,让jser()的前端工程师大开眼界,原来对数组的操作是如此的丰富多彩。原来的javascript数组方法就是基于栈与队列的一套方法,像splice()还是很晚的时候加入的。让我们回顾一下用法。

pop()方法,出栈操作,删除并返回数组的最后一个元素

push()方法,出栈操作,向数组的末尾添加一个或更多元素,并返回新的长度。

shift()方法,出队操作,删除并返回数组的第一个元素

unshift()方法,入队操作,向数组的开头添加一个或更多的元素,返回新的长度

slice()方法,切片操作,从数组中分离出一个子数组,功能类似字符串的substring、slice、substr这三兄弟。此方法也常用于转换类数组对象为真正的数组

sort()方法,对数组元素进行排序,有一个可选参数,为比较函数。

reverse()方法,颠倒数组中元素的顺序。

splice()方法,用于用于同时对原数组进行增删操作,数组的remove方法就是基于它而写的

concat()方法,用于把原数组与参数合并成一个新数组,如果参数为数组,那么它会把其第一维的元素放入新的数组中。因此我们可以利用它实现数组的平坦化操作和克隆操作。

join()方法,把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。你可以想象成字符串的split的反操作。

在ecma262v5中,它把标准浏览器早已经实现的几个方法进行了入户处理。从此,我们可以安心的使用forEach()方法,不用担心他们被废弃掉了。

indexOf()方法,定位操作。同上,不是从后遍历。索引操作可以说是字符串的同名方法的翻版,存在就返回非负操作。不存在就返回-1.

forEach()方法。迭代操作。将数组的元素依次传入一个函数中执行,prototype.js对应的名字为 each。

map()方法,收集操作。将数组的元素依次传入一个函数中执行,然后把它们的返回值组成一个新数组返回。prototype.js对应的名字为collect.

fliter()方法。过滤操作,将数组的元素依次传入一个函数中执行,然后把返回值为true的那个元素放入新的数组中返回。prototype.js中它有三个名字,select、filter、findAll

some()方法,只要数组中有一个元素满足条件(放进函数返回true)。那么它就返回true.prototype.js对应的名字为any

every()方法,只有数组的元素满足调条件(放进给定函数返回true)它才返回true。prototype.js对应的名字为any

reduce()方法,归化操作。将数组中的元素归化为一个简单的数值。prototype.js对应的名字为inject

reduceRight()方法:归化操作,将数组中的元素归化为一个简单的数值。同上,不过是从后遍历。

由于许多扩展也基于这些新的标准方法,因此我们先给出IE678兼容方案,全部在数组原型上修复他们。

(未完待续

以下将更新:

3.数值的扩展与修复

4.函数的扩展与修复

5.日期的扩展与修复

时间: 2024-11-05 00:33:26

第四章 语言模块的相关文章

perl 第十四章 Perl5的包和模块

第十四章 Perl5的包和模块 by flamephoenix 一.require函数  1.require函数和子程序库  2.用require指定Perl版本二.包  1.包的定义  2.在包间切换  3.main包  4.包的引用  5.指定无当前包  6.包和子程序  7.用包定义私有数据  8.包和系统变量  9.访问符号表三.模块  1.创建模块  2.导入模块  3.预定义模块 一.require函数    用require函数可以把程序分割成多个文件并创建函数库.例如,在myfi

《数据结构与算法分析:C语言描述》复习——第四章“树”——AVL树

2014.06.15 16:22 简介: AVL树是一种高度平衡的二叉搜索树,其命名源自于联合发明算法的三位科学家的名字的首字母.此处“平衡”的定义是:任意节点的左右子树的高度相差不超过1.有了这个平衡的性质,使得AVL树的高度H总是接近log(N),因此各种增删改查的操作的复杂度能够保证在对数级别.没有bad case是AVL树与普通的二叉搜索树的最大区别.为了实现平衡性质,我们需要记录每个节点的高度(或者平衡因子)来检测不平衡的情况.为了修正高度不平衡,需要用到“旋转”的方法,分为单旋转和双

OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)和varying,uniform,attribute修饰范围

OpenGL ES着色器语言之变量和数据类型(一)(官方文档第四章)   所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符.变量在声明的时候首先要标明类型,后边可以跟多个变量,之间用逗号隔开.很多情况下,变量在声明的时候可以使用等号“=”进行初始化. 用户定义类型可以使用struct,在结构体中所有变量类型都必须是OpenGL ES着色器语言定义的关键字.OpenGL ES着色语言是类型安全的,因此不支持隐式类型转换.

OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,uniform,纹理查找,等等),是不是顶点或者片元着色器,还有其他一些底层实现的细节.最低存储需要通过精度修饰符来声明.典型地,精度操作必须要保留变量包含的精度存储.仅有的例外是需要大量复杂计算的内建函数,如atan(),返回值的精度低于声明的精度. 强烈建议顶点语言提供一种匹配IEEE单精度浮点数或更高精

Head First Python 第二章 函数模块&amp;第三章 文件与异常&amp;第四章 持久存储&amp;第五章 处理数据

第三章 1.共享模块 模块和发布工具箱全世界共享模块 编写函数,以.py为文件后缀名,第三方库都在PyPI *注释代码:三引号(单双都可以) 发布过程P40 使用发布工具,函数模块变成了一个“发布”,可以使用import导入其他程序 2.如果函数模块功能不满意 添加参数以供api选择比添加函数工作量小! 首先考虑BIF内置函数 ----------------------------------------------------------- 第四章 1.文件 open()语句,readlin

Python 3标准库 第十四章 应用构建模块

Python 3标准库 The Python3 Standard Library by  Example -----------------------------------------第十四章     应用构建模块-----------------------------14.1  argparse:命令行选项和参数解析----------------------------- argparse模块 14.1.1  建立解析器 14.1.2  定义参数 argparse模块 14.1.3 

Java语言程序设计(基础篇) 第四章 数学函数、字符和字符串

第四章 数学函数.字符和字符串 4.2 常用数学函数 方法分三类:三角函数方法(trigonometric method).指数函数方法(exponent method)和服务方法(service method) 4.4 String类型 String类型不是基本类型,而是引用类型(reference type).

第四章 初步进入linux世界

第四章 初步进入linux世界 [Linux 系统启动过程] Linux的启动其实和windows的启动过程很类似,不过windows我们是无法看到启动信息的,而linux启动时我们会看到许多启动信息,例如某个服务是否启动. Linux系统的启动过程大体上可分为五部分:内核的引导:运行init:系统初始化:建立终端 :用户登录系统. A 内核引导 当计算机打开电源后,首先是BIOS开机自检,按照BIOS中设置的启动设备(通常是硬盘)来启动.紧接着由启动设备上的grub程序开始引导linux,当引

第三章:模块加载系统(requirejs)

任何一门语言在大规模应用阶段,必然要经历拆分模块的过程.便于维护与团队协作,与java走的最近的dojo率先引入加载器,早期的加载器都是同步的,使用document.write与同步Ajax请求实现.后来dojo开始以JSONP的方法设计它的每个模块结构.以script节点为主体加载它的模块.这个就是目前主流的加载器方式. 不得不提的是,dojo的加载器与AMD规范的发明者都是james Burke,dojo加载器独立出来就是著名的require.本章将深入的理解加载器的原理. 1.AMD规范