资讯专栏INFORMATION COLUMN

ES6学习摘要(03)(新人学习)

番茄西红柿 / 1013人阅读

摘要:字符的表示法允许采用形式表示一个字符,其中表示字符的码点。方法,用来将字符的不同表示方法统一为同样的形式,这称为正规化。,默认参数,表示标准等价合成,返回多个简单字符的合成字符。返回布尔值,表示参数字符串是否在原字符串的头部。

ECMAScript6/ES6 入门

let和const命令
变量的解构赋值

五、字符串的扩展

注:这章没什么可以理解的,看过一遍就行,所以大体上我把有用的一些东西拷过来给大家看下。
1、字符的Unicode表示法
JavaScript 允许采用uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。但是,这种表示法只限于码点在u0000~uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。如果直接在u后面跟上超过0xFFFF的数值(比如u20BB7),JavaScript 会理解成u20BB+7。由于u20BB是一个不可打印字符,所以只会显示一个空格,后面跟着一个7。

"uD842uDFB7"
// "?"

"u20BB7"
// " 7"

在ES6中做了处理,只要将码点放入大括号,就能正确解读该字符。有了这种表示法之后,JavaScript 共有 6 种方法可以表示一个字符。

"u{20BB7}"
// "?"

"u{41}u{42}u{43}"
// "ABC"

let hello = 123;
hellu{6F} // 123

"u{1F680}" === "uD83DuDE80"
// true
"z" === "z"  // true
"172" === "z" // true
"x7A" === "z" // true
"u007A" === "z" // true
"u{7A}" === "z" // true

2、codePointAt()
对于原来的charAtcharCodeAt,是无法获取4个字节的字符串的,charCodeAt方法只能分别返回前两个字节和后两个字节的值。而有些汉字是需要4个字节的,比如:汉字“?”(注意,这个字不是“吉祥”的“吉”)的码点是0x20BB7

var s = "?";

s.length // 2
s.charAt(0) // ""
s.charAt(1) // ""
s.charCodeAt(0) // 55362
s.charCodeAt(1) // 57271

所以在ES6中提供了codePointAt方法,能够正确返回4个字节存储的字符串。

let s = "?a";

s.codePointAt(0) // 134071
s.codePointAt(1) // 57271

s.codePointAt(2) // 97

有的人就要问了,codePointAt方法为啥是3个字符(0,1,2)?首先,JavaScript肯定是将"?a"视作3个字符的,只是ES6方法不同而已,codePointAt(0)返回的是第一字符"?",codePointAt(1)返回的是"?"(共4个字节)的后两个字节,codePointAt(2)返回的是"a"。也就是说后两个字节,codePointAt方法的结果与charCodeAt方法相同。
同时,从上面的例子可以看出,codePointAt方法返回的是码点的十进制值,如果想要十六进制的值,可以使用toString方法转换一下。

let s = "?a";

s.codePointAt(0).toString(16) // "20bb7"
s.codePointAt(2).toString(16) // "61"

可能这样看上去感觉怪怪的,毕竟只有两个字符,写的时候还要去注意0,2,其实有更好的解决办法,利用for...of循环,直接看例子:

let s = "?a";
for (let ch of s) {
  console.log(ch.codePointAt(0).toString(16));
}
// 20bb7
// 61

3、String.fromCodePoint()
String.fromCharCode用于从码点返回对应字符,但是这个方法不能识别 32 位的 UTF-16 字符(Unicode 编号大于0xFFFF)。

String.fromCharCode(0x20BB7)
// "ஷ"

ES6 提供了String.fromCodePoint方法,可以识别大于0xFFFF的字符,弥补了String.fromCharCode方法的不足。在作用上,正好与codePointAt方法相反。

String.fromCodePoint(0x20BB7)
// "?"
String.fromCodePoint(0x78, 0x1f680, 0x79) === "xuD83DuDE80y"
// true

4、字符串的遍历器接口

for (let codePoint of "foo") {
  console.log(codePoint)
}
// "f"
// "o"
// "o"

for...of循环遍历,这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。
5、at()
同上,charAt不能识别码点大于0xFFFF的字符。at则可以。

"abc".at(0) // "a"
"?".at(0) // "?"

6、normalize()
normalize()方法,用来将字符的不同表示方法统一为同样的形式,这称为 Unicode 正规化。
许多欧洲语言有语调符号和重音符号。为了表示它们,Unicode 提供了两种方法。一种是直接提供带重音符号的字符,比如Ǒ(u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如O(u004F)ˇ(u030C)合成Ǒ(u004Fu030C)

"u01D1"==="u004Fu030C" //false

"u01D1".normalize() === "u004Fu030C".normalize()
// true
normalize方法可以接受一个参数来指定normalize的方式,参数的四个可选值如下。

NFC,默认参数,表示“标准等价合成”(Normalization Form Canonical Composition),返回多个简单字符的合成字符。所谓“标准等价”指的是视觉和语义上的等价。
NFD,表示“标准等价分解”(Normalization Form Canonical Decomposition),即在标准等价的前提下,返回合成字符分解的多个简单字符。
NFKC,表示“兼容等价合成”(Normalization Form Compatibility Composition),返回合成字符。所谓“兼容等价”指的是语义上存在等价,但视觉上不等价,比如“囍”和“喜喜”。(这只是用来举例,normalize方法不能识别中文。)
NFKD,表示“兼容等价分解”(Normalization Form Compatibility Decomposition),即在兼容等价的前提下,返回合成字符分解的多个简单字符。

7、includes(), startsWith(), endsWith()
indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。

includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = "Hello world!";

s.startsWith("Hello") // true
s.endsWith("!") // true
s.includes("o") // true

这三个方法都支持第二个参数,表示开始搜索的位置。

let s = "Hello world!";

s.startsWith("world", 6) // true
s.endsWith("Hello", 5) // true
s.includes("Hello", 6) // false

8、repeat()
repeat方法返回一个新字符串,表示将原字符串重复n次。参数如果是小数,会被取整。如果repeat的参数是负数或者Infinity,会报错。

"x".repeat(3) // "xxx"
"na".repeat(2.9) // "nana"
"na".repeat(0) // ""
"na".repeat(Infinity)
// RangeError
"na".repeat(-1)
// RangeError

但是,如果参数是 0 到-1 之间的小数,则等同于 0,这是因为会先进行取整运算。0 到-1 之间的小数,取整以后等于-0,repeat视同为 0。

"na".repeat(-0.9) // ""

参数NaN等同于 0。

"na".repeat(NaN) // ""

如果repeat的参数是字符串,则会先转换成数字。

"na".repeat("na") // ""
"na".repeat("3") // "nanana"

9、padStart(),padEnd()
如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

"x".padStart(5, "ab") // "ababx"
"x".padStart(4, "ab") // "abax"

"x".padEnd(5, "ab") // "xabab"
"x".padEnd(4, "ab") // "xaba"

如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。

"xxx".padStart(2, "ab") // "xxx"
"xxx".padEnd(2, "ab") // "xxx"

如果省略第二个参数,默认使用空格补全长度。

"x".padStart(4) // "   x"
"x".padEnd(4) // "x   "

padStart的常见用途是为数值补全指定位数。下面代码生成 10 位的数值字符串。

"1".padStart(10, "0") // "0000000001"
"12".padStart(10, "0") // "0000000012"
"123456".padStart(10, "0") // "0000123456"

10、模板字符串
用反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

// 普通字符串
`In JavaScript "
" is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入变量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

11、实例:模板编译

let template = `
    <% for(let i=0; i < data.supplies.length; i++) { %>
  • <%= data.supplies[i] %>
  • <% } %>
`;

上面代码在模板字符串之中,放置了一个常规模板。该模板使用<%...%>放置 JavaScript 代码,使用<%= ... %>输出 JavaScript 表达式。
怎么编译这个模板字符串呢?

一种思路是将其转换为 JavaScript 表达式字符串。

echo("
    "); for(let i=0; i < data.supplies.length; i++) { echo("
  • "); echo(data.supplies[i]); echo("
  • "); }; echo("
");

这个转换使用正则表达式就行了。

let evalExpr = /<%=(.+?)%>/g;
let expr = /<%([sS]+?)%>/g;

template = template
  .replace(evalExpr, "`); 
  echo( $1 ); 
  echo(`")
  .replace(expr, "`); 
 $1 
  echo(`");

template = "echo(`" + template + "`);";

然后,将template封装在一个函数里面返回,就可以了。

let script =
`(function parse(data){
  let output = "";

  function echo(html){
    output += html;
  }

  ${ template }

  return output;
})`;

return script;

将上面的内容拼装成一个模板编译函数compile。

function compile(template){
  const evalExpr = /<%=(.+?)%>/g;
  const expr = /<%([sS]+?)%>/g;

  template = template
    .replace(evalExpr, "`); 
  echo( $1 ); 
  echo(`")
    .replace(expr, "`); 
 $1 
  echo(`");

  template = "echo(`" + template + "`);";

  let script =
  `(function parse(data){
    let output = "";

    function echo(html){
      output += html;
    }

    ${ template }

    return output;
  })`;

  return script;
}

compile函数的用法如下。

let parse = eval(compile(template));
div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });
//   
    //
  • broom
  • //
  • mop
  • //
  • cleaner
  • //

11、String.raw()
String.raw方法,往往用来充当模板字符串的处理函数,返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,对应于替换变量后的模板字符串。

String.raw`Hi
${2+3}!`;
// "Hi
5!"

String.raw`Hiu000A!`;
// "Hiu000A!"

如果原字符串的斜杠已经转义,那么String.raw不会做任何处理。

String.raw`Hi
`
// "Hi
"

String.raw的代码基本如下。

String.raw = function (strings, ...values) {
  let output = "";
  let index;
  for (index = 0; index < values.length; index++) {
    output += strings.raw[index] + values[index];
  }

  output += strings.raw[index]
  return output;
}

String.raw方法可以作为处理模板字符串的基本方法,它会将所有变量替换,而且对斜杠进行转义,方便下一步作为字符串来使用。

String.raw方法也可以作为正常的函数使用。这时,它的第一个参数,应该是一个具有raw属性的对象,且raw属性的值应该是一个数组。

String.raw({ raw: "test" }, 0, 1, 2);
// "t0e1s2t"

// 等同于

String.raw({ raw: ["t","e","s","t"] }, 0, 1, 2);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92248.html

相关文章

  • ES6学习摘要(01)(新人学习

    摘要:入门一前言由于最近本人在学习,做一些笔记能够更好的熟悉,就趁此机会来写一篇关于的新人学习摘要吧。的作用域与命令相同只在声明所在的块级作用域内有效。块级作用域新增方式和实际上为新增了块级作用域。同时,函数声明还会提升到所在的块级作用域的头部。 ECMAScript6/ES6 入门 一、前言 由于最近本人在学习ES6,做一些笔记能够更好的熟悉,就趁此机会来写一篇关于ES6的新人学习摘要吧。...

    dmlllll 评论0 收藏0
  • ES6学习摘要(02)(新人学习

    摘要:默认值同时,对象解构赋值也允许设置默认值,默认值生效的判断条件同数组,只有在对应值严格等于时会生效。报错如果要将一个已经声明的变量用于解构赋值,必须非常小心。的规则是,只要有可能导致解构的歧义,就不得使用圆括号。 ECMAScript6/ES6 入门 let和const命令 四、变量的解构赋值 在ES6之前,数组和对象属性赋值只能直接指定固定值,ES6 允许按照一定模式,从数组和对象中...

    Jonathan Shieber 评论0 收藏0
  • 2017前端现状--答题救不了前端新人

    摘要:众所周知,前端近几年闹了一场革命。这些问题反应了什么现象确实前端很火,引来了一批批新人。前端小白们如火如荼的学习着现在前端流行的新技术栈。写在最后所以啊,在目睹了很多白痴问题后,我终于发出了一声呐喊,答题救不了前端新人。 众所周知,前端近几年闹了一场革命。前端在编程领域也掀起了学习潮。至少在中国,从2013年下半年至今,在搜索指数上,有着爆炸式的增长。可以看下数据:百度指数,Googl...

    jone5679 评论0 收藏0
  • 2017前端现状--答题救不了前端新人

    摘要:众所周知,前端近几年闹了一场革命。这些问题反应了什么现象确实前端很火,引来了一批批新人。前端小白们如火如荼的学习着现在前端流行的新技术栈。写在最后所以啊,在目睹了很多白痴问题后,我终于发出了一声呐喊,答题救不了前端新人。 众所周知,前端近几年闹了一场革命。前端在编程领域也掀起了学习潮。至少在中国,从2013年下半年至今,在搜索指数上,有着爆炸式的增长。可以看下数据:百度指数,Googl...

    alogy 评论0 收藏0
  • 刚进入软件测试行业的新人,这些宝贵经验要收好~

    摘要:软件测试从宏观上可以分为功能测试性能测试安全性测试三个方面,如果能将三者结合起来就说明已经将这个岗位做的十分好了。 恍然间,发现自己已经在这个行业五年之久,回顾过往,思绪良多,一路走来,或多或少都经历过一些坎坷,也碰到过不少大大小小的困难。在此就不多加叙述了。 本篇文章主要想写给刚入门的测...

    马永翠 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<