多互联网新鲜资讯、工作奇淫技巧关注原创【飞鱼在浪屿】(日更新)
Unicode是涵盖世界上大多数书写系统。用在网络,大多数操作系统,Java和.NET的标准编码等。
在Unicode诞生之前,都有自己的编码,它们都不同,而且不兼容编码。而Unicode是几乎所有字符的超集,因此可以用于互换信息。
它诞生至今30多年了。
在开始下文之前,如果遇到查询unicode代码的,可以使用工具类网站https://unicode.yunser.com/unicode
Unicode 为每个字符(例如a,ã, ې,不和☃)定义一个代码/数字。从Unicode 6.2开始(http://www.unicode.org/versions/Unicode6.2.0/),共有109,976个代码!
它还包括组合字符,诸如◌̀之类,这些字符可以添加到其他字符中;这样,Unicode不需要字母和重音的每种可能组合设置一个代码。另一方面,Unicode的一般不关心字体或风格上的区别:比如下面两个是同一种字符:
Unicode不只是字符集合。它还涵盖了诸如UTF-8之类的标准编码。小写/大写/标题大小写映射,整理(排序),换行符,从右到左的脚本的渲染处理等。
因为Unicode是其他编码的超集,所以它有时包括同一个字符,但是却有多个不同的代码,例如,以下三个:
python输出
为了使它们在相等性测试等中被视为相同的字符串,您应该通过Unicode规范(http://unicode.org/reports/tr15/)运行所有输入。最常见的形式是 NFC(Normalisation Form C),它尽可能使用预先组合字符,并如果存在多个,则一个严格的顺序定义这变音符号。NFD D(Normalisation Form D)则尽可能撰写1个字符。只要您保持一致,使用哪种形式都没有关系。NFD通常更快(代码点更少),建议通过NFD运行输入,并通过NFC输出。
Compatibility decomposition/兼容性分解(NFKC,compatibility decomposition + canonical composition)会把ffi,Ⅸ和甚至⁵映射为为“FFI”,“IX”和“5”分别。搜索文本时,这种NFKC规范化功能会起到帮助。
在Unicode世界中,大小写并不是那么简单:
为了确保您的代码能够处理这些情况以及任何新的情况,Unicode提供了 一种单向 “ casefold”操作,该操作允许不区分大小写的比较。
排序(或排序规则)是特定于语言环境的,并且像大小写一样充满特殊性:
仅通过二进制比较进行排序是不够的。而且,代码点通常也不是明智的。幸运的是,Unicode指定了一种 可高度自定义的归类算法,该算法涵盖了所有边缘情况,并且做了一些巧妙的工作以使其变得相当快。这是一个示例:2
该UCA可以把“10”和“2”视为数值,如排序“10”“放在“2”后面?” 。把“?”视为字符串“问号”。
大端序有UTF-8,UTF-16和UTF-32。每种编码都保证几乎每个码点和字节序列的可逆映射。
国际字符 给域名带来了一个大问题。就像 I (I 0049 拉丁文大写 I)和 l(l 006C拉丁L的小写) 看起来很相似一样,Unicode除了增加了许多不可见的控制字符,空格字符和从右到左的文本外,还将这个问题放大很多。
浏览器和注册商已针对此采取了几种措施:
RFC 3491定义了nameprep,一种在字符串可以在域名中使用之前对字符串进行大小写折叠,规范化和清理的机制。如果使用了禁止的代码点,这将删除许多不可见的字符并抛出异常。
出于传统原因,DNS不允许ASCII之外的扩展字符,因此Punycode是ASCII兼容的编码方案。例如,café.com变为xn--caf-dma.com。所有Punycode编码的域组件都可以通过其xn--前缀立即识别。
这也适用于顶级域名 :比如中国的代码为xn-fiqs8s。
在Perl至少,一切(substr,length,index,reverse...)操作是以代码点为准。但这通常不是你想要的,因为用户认为像ў这样的字符实际上是两个代码点(y + ◌̆)。
甚至看似没问题的东西,例如printf "%-10s", $str完全中断组合字符,全角字符(例如中文/日文)或零角字符的操作。
一旦涉及到Unicode ,换行(或自动换行)就变得异常复杂。您必须考虑各种不间断和不间断的控制和空格字符,每种语言中的标点符号(例如«和»引号或数字中使用的句号或逗号)以及每个字符的宽度。
当您使用Unicode字符串作为文件或目录名称时,所有操作都不好用。使用什么编码?使用什么API?(Windows有两种,一种使用Unicode,另一种尝试使用与语言环境相关的编码)。Mac OSX文件系统则会执行规范化,例如对文件名执行NFD。如果您的平台不了解分解后的Unicode,则可能会出现问题。
汉字是中文,日文(汉字)以及韩文和越南文的共同特征。根据脚本的不同,许多脚本都有独特的视觉外观,但是Unicode出于简化和性能的原因将它们统一为一个代码点(示例)。
这引起了争议,因为角色的视觉形式可能有意义;可能不会向用户显示他们的国家/地区版本,而是其他国家/地区的版本。在某些情况下,它们看起来可能非常不同(例如,直)。正如西方名称的变化(例如“ John”或“ Jon”)一样,日语名称可能使用Unicode无法提供的特定字形变体,因此人们实际上无法以自己喜欢的方式来写自己的名字!
实际上,用户选择一种字体以其想要的样式呈现字形,无论是日语还是中文。变体选择器(参见下文)是解决该问题的另一种方法。
由于政治和遗留原因(与旧字符集兼容),Unicode不会尝试统一简体和繁体中文。
Unicode 6.0版增加了722个“表情符号”字符,这些表情符号通常在日语手机上使用,但最近在Mac OS X(Lion),Gmail,iPhone和Windows Phone 7中使用。某些字体可能选择将其呈现为全彩色表情符号。 ; 有些则可能根本不支持他们。
表情符号的Unicode表示,包含你熟悉的LOVE HOTEL 和PILE OF POO
Unicode 6.0的表情符号为许多国家(地区)标志引入了符号,但并不是全部国家。作为一种可选方案,范围U + 1F1E6 .. U + 1F1FF 定义了从A到Z的符号。如果该范围中的两个符号形成了ISO-3166-1国家代码(例如,法国的“ FR”),则渲染器可以显示为国旗!
变体选择器是代码点,可更改渲染字符之前的字符方式。有256个,它们占据的范围为U + FE00 .. U + FE0F 和U + E0100.. U + E01EF加上U + 180B,U + 180C和U + 180D。
它们对于蒙古语脚本来说是必不可少的,蒙古语脚本具有不同的字形形式,具体取决于其在单词中的位置,单词的性别,附近有哪些字母,单词是否为外国单词以及现代与传统拼字法(详细信息)。
预计这些将用于提供由Han Unification统一的字形的变体。
它们还用于更深奥的事物,例如数学运算符的衬线版本。
页能将文本、图片、音频、视频等诸多元素结合起来,通过CSS,能呈现这些元素预定的外观,通过JavaScrip脚本,能呈现预定的动作。
网页设计前端语言HTML、HTML、JavaScript三者关系:
前端网页语言 | 功能 | 说明 | 符号 |
HTML | 内容 | Hyper Text Markup Language | <tag>…</tag> |
CSS | 内容呈现的外观 | Cascading Style Sheets | <style>...</style> |
JavaScript | 内容呈现的动作 | 嵌入网页有脚本 | <script>...</script> |
以上由浏览器解释执行。
代码举例:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>前端语言比较</title>
</head>
<style>
#container{
margin:auto;
width:75%;
}
.descri{
color:#990000;
font-size:120%;
}
</style>
<body>
<div id="container">
<h4>前端语言比较</h4>
<p class="descri">简单加法器:</p>
<form name="myform">
加数:<input type="text" name="first" size="6" />
<span style="color:red;">+</span> 被加数
<input type="text" name="second" size="6" />
<input type="button" onclick="sum()" value="求和" />
<span style="color:blue;">=</span>
<input type="text" name="result" size="6" />
</form>
</div>
<script type="text/javascript">
function sum(){
var resultValue,firstValue,secondValue;
firstValue = parseFloat(document.myform.first.value);
secondValue = parseFloat(document.myform.second.value);
resultValue = parseFloat(firstValue + secondValue);
document.myform.result.value = resultValue;
}
</script>
</body>
</html>
Chrome浏览器呈现:
HTML,Hyper Text Markup Language,就其字面理解,其核心是"Markup“(标记),通过“标记”,让将文本、图片、音频、视频等诸多元素呈现“超文本”(HyperText)的特点。
CSS,Cascading Style Sheets,就其字面理解,其核心是“Style“,也就是”样式“。就像我们做Word文档一样,对文本进行格式化。但在网页设计中,样式是通过“属性:属性值“的代码来表示,且这些“样式”可以叠加,对对象的样式描述可以列成序列的形式;
JavaScript,是一种网页脚本语言,通过网页中的一些事件能引发一些代码的执行。
最好的参考网站或查询页面:http://www.w3school.com.cn/index.html
们从学校里了解到过很多运算符,比如说加号 +、乘号 *、减号 - 等。
在本章中,我们将从简单的运算符开始,然后着重介绍 JavaScript 特有的方面,这些是在学校中学习的数学所没有涵盖的。
在正式开始前,我们先简单浏览一下常用术语。
支持以下数学运算:
前四个都很简单,而 % 和 ** 则需要说一说。
取余运算符是 %,尽管它看起来很像百分数,但实际并无关联。
a % b 的结果是 a 整除 b 的 余数)。
例如:
alert( 5 % 2 ); // 1,5 除以 2 的余数
alert( 8 % 3 ); // 2,8 除以 3 的余数
求幂运算 a ** b 将 a 提升至 a 的 b 次幂。
在数学中我们将其表示为 ab。
例如:
alert( 2 ** 2 ); // 2² = 4
alert( 2 ** 3 ); // 2³ = 8
alert( 2 ** 4 ); // 2⁴ = 16
就像在数学计算中一样,幂运算也适用于非整数。
例如,平方根是指数为 ½ 的幂运算:
alert( 4 ** (1/2) ); // 2(1/2 次方与平方根相同)
alert( 8 ** (1/3) ); // 2(1/3 次方与立方根相同)
我们来看一些学校算术未涉及的 JavaScript 运算符的特性。
通常,加号 + 用于求和。
但是如果加号 + 被应用于字符串,它将合并(连接)各个字符串:
let s = "my" + "string";
alert(s); // mystring
注意:只要任意一个运算元是字符串,那么另一个运算元也将被转化为字符串。
举个例子:
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
你看,第一个运算元和第二个运算元,哪个是字符串并不重要。
下面是一个更复杂的例子:
alert(2 + 2 + '1' ); // "41",不是 "221"
在这里,运算符是按顺序工作。第一个 + 将两个数字相加,所以返回 4,然后下一个 + 将字符串 1 加入其中,所以就是 4 + '1' = '41'。
alert('1' + 2 + 2); // "122",不是 "14"
这里,第一个操作数是一个字符串,所以编译器将其他两个操作数也视为了字符串。2 被与 '1' 连接到了一起,也就是像 '1' + 2 = "12" 然后 "12" + 2 = "122" 这样。
二元 + 是唯一一个以这种方式支持字符串的运算符。其他算术运算符只对数字起作用,并且总是将其运算元转换为数字。
下面是减法和除法运算的示例:
alert( 6 - '2' ); // 4,将 '2' 转换为数字
alert( '6' / '2' ); // 3,将两个运算元都转换为数字
加号 + 有两种形式。一种是上面我们刚刚讨论的二元运算符,还有一种是一元运算符。
一元运算符加号,或者说,加号 + 应用于单个值,对数字没有任何作用。但是如果运算元不是数字,加号 + 则会将其转化为数字。
例如:
// 对数字无效
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
// 转化非数字
alert( +true ); // 1
alert( +"" ); // 0
它的效果和 Number(...) 相同,但是更加简短。
我们经常会有将字符串转化为数字的需求。比如,如果我们正在从 HTML 表单中取值,通常得到的都是字符串。如果我们想对它们求和,该怎么办?
二元运算符加号会把它们合并成字符串:
let apples = "2";
let oranges = "3";
alert( apples + oranges ); // "23",二元运算符加号合并字符串
如果我们想把它们当做数字对待,我们需要转化它们,然后再求和:
let apples = "2";
let oranges = "3";
// 在二元运算符加号起作用之前,所有的值都被转化为了数字
alert( +apples + +oranges ); // 5
// 更长的写法
// alert( Number(apples) + Number(oranges) ); // 5
从一个数学家的视角来看,大量的加号可能很奇怪。但是从一个程序员的视角,没什么好奇怪的:一元运算符加号首先起作用,它们将字符串转为数字,然后二元运算符加号对它们进行求和。
为什么一元运算符先于二元运算符作用于运算元?接下去我们将讨论到,这是由于它们拥有 更高的优先级。
如果一个表达式拥有超过一个运算符,执行的顺序则由 优先级 决定。换句话说,所有的运算符中都隐含着优先级顺序。
从小学开始,我们就知道在表达式 1 + 2 * 2 中,乘法先于加法计算。这就是一个优先级问题。乘法比加法拥有 更高的优先级。
圆括号拥有最高优先级,所以如果我们对现有的运算顺序不满意,我们可以使用圆括号来修改运算顺序,就像这样:(1 + 2) * 2。
在 JavaScript 中有众多运算符。每个运算符都有对应的优先级数字。数字越大,越先执行。如果优先级相同,则按照由左至右的顺序执行。
这是一个摘抄自 Mozilla 的 优先级表(你没有必要把这全记住,但要记住一元运算符优先级高于二元运算符):
优先级 | 名称 | 符号 |
… | … | … |
15 | 一元加号 | + |
15 | 一元负号 | - |
14 | 求幂 | ** |
13 | 乘号 | * |
13 | 除号 | / |
12 | 加号 | + |
12 | 减号 | - |
… | … | … |
2 | 赋值符 | = |
… | … | … |
我们可以看到,“一元加号运算符”的优先级是 15,高于“二元加号运算符”的优先级 12。这也是为什么表达式 "+apples + +oranges" 中的一元加号先生效,然后才是二元加法。
我们知道赋值符号 = 也是一个运算符。从优先级表中可以看到它的优先级非常低,只有 2。
这也是为什么,当我们赋值时,比如 x = 2 * 2 + 1,所有的计算先执行,然后 = 才执行,将计算结果存储到 x。
let x = 2 * 2 + 1;
alert( x ); // 5
= 是一个运算符,而不是一个有着“魔法”作用的语言结构。
在 JavaScript 中,所有运算符都会返回一个值。这对于 + 和 - 来说是显而易见的,但对于 = 来说也是如此。
语句 x = value 将值 value 写入 x 然后返回 x。
下面是一个在复杂语句中使用赋值的例子:
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
alert( a ); // 3
alert( c ); // 0
上面这个例子,(a = b + 1) 的结果是赋给 a 的值(也就是 3)。然后该值被用于进一步的运算。
有趣的代码,不是吗?我们应该了解它的工作原理,因为有时我们会在 JavaScript 库中看到它。
不过,请不要写这样的代码。这样的技巧绝对不会使代码变得更清晰或可读。
另一个有趣的特性是链式赋值:
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
链式赋值从右到左进行计算。首先,对最右边的表达式 2 + 2 求值,然后将其赋给左边的变量:c、b 和 a。最后,所有的变量共享一个值。
同样,出于可读性,最好将这种代码分成几行:
c = 2 + 2;
b = c;
a = c;
这样可读性更强,尤其是在快速浏览代码的时候。
我们经常需要对一个变量做运算,并将新的结果存储在同一个变量中。
例如:
let n = 2;
n = n + 5;
n = n * 2;
可以使用运算符 += 和 *= 来缩写这种表示。
let n = 2;
n += 5; // 现在 n = 7(等同于 n = n + 5)
n *= 2; // 现在 n = 14(等同于 n = n * 2)
alert( n ); // 14
所有算术和位运算符都有简短的“修改并赋值”运算符:/= 和 -= 等。
这类运算符的优先级与普通赋值运算符的优先级相同,所以它们在大多数其他运算之后执行:
let n = 2;
n *= 3 + 5;
alert( n ); // 16 (右边部分先被计算,等同于 n *= 8)
对一个数进行加一、减一是最常见的数学运算符之一。
所以,对此有一些专门的运算符:
重要:
自增/自减只能应用于变量。试一下,将其应用于数值(比如 5++)则会报错。
运算符 ++ 和 -- 可以置于变量前,也可以置于变量后。
两者都做同一件事:将变量 counter 与 1 相加。
那么它们有区别吗?有,但只有当我们使用 ++/-- 的返回值时才能看到区别。
详细点说。我们知道,所有的运算符都有返回值。自增/自减也不例外。前置形式返回一个新的值,但后置返回原来的值(做加法/减法之前的值)。
为了直观看到区别,看下面的例子:
let counter = 1;
let a = ++counter; // (*)
alert(a); // 2
(*) 所在的行是前置形式 ++counter,对 counter 做自增运算,返回的是新的值 2。因此 alert 显示的是 2。
下面让我们看看后置形式:
let counter = 1;
let a = counter++; // (*) 将 ++counter 改为 counter++
alert(a); // 1
(*) 所在的行是后置形式 counter++,它同样对 counter 做加法,但是返回的是 旧值(做加法之前的值)。因此 alert 显示的是 1。
总结:
自增/自减和其它运算符的对比
++/-- 运算符同样可以在表达式内部使用。它们的优先级比绝大部分的算数运算符要高。
举个例子:
let counter = 1;
alert( 2 * ++counter ); // 4
与下方例子对比:
let counter = 1;
alert( 2 * counter++ ); // 2,因为 counter++ 返回的是“旧值”
尽管从技术层面上来说可行,但是这样的写法会降低代码的可阅读性。在一行上做多个操作 —— 这样并不好。
当阅读代码时,快速的视觉“纵向”扫描会很容易漏掉 counter++,这样的自增操作并不明显。
我们建议用“一行一个行为”的模式:
let counter = 1;
alert( 2 * counter );
counter++;
位运算符把运算元当做 32 位整数,并在它们的二进制表现形式上操作。
这些运算符不是 JavaScript 特有的。大部分的编程语言都支持这些运算符。
下面是位运算符:
这些运算符很少被使用,一般是我们需要在最低级别(位)上操作数字时才使用。我们不会很快用到这些运算符,因为在 Web 开发中很少使用它们,但在某些特殊领域中,例如密码学,它们很有用。当你需要了解它们的时候,可以阅读 MDN 上的 位操作符 章节。
逗号运算符 , 是最少见最不常使用的运算符之一。有时候它会被用来写更简短的代码,因此为了能够理解代码,我们需要了解它。
逗号运算符能让我们处理多个语句,使用 , 将它们分开。每个语句都运行了,但是只有最后的语句的结果会被返回。
举个例子:
let a = (1 + 2, 3 + 4);
alert( a ); // 7(3 + 4 的结果)
这里,第一个语句 1 + 2 运行了,但是它的结果被丢弃了。随后计算 3 + 4,并且该计算结果被返回。
逗号运算符的优先级非常低
请注意逗号运算符的优先级非常低,比 = 还要低,因此上面你的例子中圆括号非常重要。
如果没有圆括号:a = 1 + 2, 3 + 4 会先执行 +,将数值相加得到 a = 3, 7,然后赋值运算符 = 执行 a = 3,然后逗号之后的数值 7 不会再执行,它被忽略掉了。相当于 (a = 1 + 2), 3 + 4。
为什么我们需要这样一个运算符,它只返回最后一个值呢?
有时候,人们会使用它把几个行为放在一行上来进行复杂的运算。
举个例子:
// 一行上有三个运算符
for (a = 1, b = 3, c = a * b; a < 10; a++) {
...
}
这样的技巧在许多 JavaScript 框架中都有使用,这也是为什么我们提到它。但是通常它并不能提升代码的可读性,使用它之前,我们要想清楚。
重要程度: 5
以下代码中变量 a、b、c、d 的最终值分别是多少?
let a = 1, b = 1;
let c = ++a; // ?
let d = b++; // ?
解决方案
重要程度: 3
下面这段代码运行完成后,代码中的 a 和 x 的值是多少?
let a = 2;
let x = 1 + (a *= 2);
解决方案
重要程度: 5
下面这些表达式的结果是什么?
"" + 1 + 0
"" - 1 + 0
true + false
6 / "3"
"2" * "3"
4 + 5 + "px"
"$" + 4 + 5
"4" - 2
"4px" - 2
" -9 " + 5
" -9 " - 5
null + 1
undefined + 1
" \t \n" - 2
好好思考一下,把它们写下来然后和答案比较一下。
解决方案
重要程度: 5
这里有一段代码,要求用户输入两个数字并显示它们的总和。
它的运行结果不正确。下面例子中的输出是 12(对于默认的 prompt 的值)。
为什么会这样?修正它。结果应该是 3。
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);
alert(a + b); // 12
解决方案
原因是 prompt 以字符串的形式返回用户的输入。
所以变量的值分别为 "1" 和 "2"。
let a = "1"; // prompt("First number?", 1);
let b = "2"; // prompt("Second number?", 2);
alert(a + b); // 12
我们应该做的是,在 + 之前将字符串转换为数字。例如,使用 Number() 或在 prompt 前加 +。
例如,就在 prompt 之前加 +:
let a = +prompt("First number?", 1);
let b = +prompt("Second number?", 2);
alert(a + b); // 3
或在 alert 中:
let a = prompt("First number?", 1);
let b = prompt("Second number?", 2);
alert(+a + +b); // 3
在最新的代码中,同时使用一元和二元的 +。看起来很有趣,不是吗?
*请认真填写需求信息,我们会在24小时内与您取得联系。