字符串的扩展

js

  1. 字符的 Unicode 表示法
  2. codePointAt()
  3. String.fromCodePoint()
  4. 字符串的遍历器接口
  5. at()
  6. normalize()  【许多欧洲语言有语调符号和重音符号】
  7. includes(), startsWith(), endsWith()
  8. repeat()
  9. padStart(),padEnd()  【字符串补全长度的功能】
  10. matchAll()
  11. 模板字符串
  12. 实例:模板编译
  13. 标签模板
  14. String.raw()
  15. 模板字符串的限制

Ref: 模板字符串

策略:${var},放在反引号中!

通过tag来表示字符串。

使用for输出完整的字符串,记得最后一个strings[strings.length-1]。

c#

Ref: 一个非常好的C#字符串操作处理类StringHelper.cs

Ref: 字符串(C# 编程指南)

Ref: 常用C#字符串函数大全

正则表达式的扩展

js

修饰符:

    • i(intensity)  :大小写不敏感。
    • g(global)    :全局查找,对于一些特定的函数,将迭代完整的字符串,获得所有的匹配结果,而不仅仅在得到第一个匹配后就停止进行。
    • m(multiple):检测字符串中的换行符,主要是影响字符串开始标识符^和结束标识符$的使用。
  1. var urlReg = /(\w+):\/\/([\w.]+)\/(\S*)/;
  2. var myHomepage = "http://www.wanjilong.com/homepage";
  3. var result = myHomepage.match(urlReg);
  4. console.log(result);
  5. for (var i = 0, len = result.length; i < len; ++i) {
  6. console.log(i, result[i]);
  7. }

Ref: JavaScript 正则表达式

Ref: JavaScript RegExp 对象

  1. var patt = new RegExp(pattern,modifiers);
  2.  
  3. 或者,更简单的方法
  4.  
  5. var patt = /pattern/modifiers;

test():一个字符串是否匹配某个模式

exec():检索字符串中的正则表达式的匹配

Method Description
exec RegExp method that executes a search for a match in a string. It returns an array of information or null on a mismatch.
test RegExp method that tests for a match in a string. It returns true or false.
match String method that executes a search for a match in a string. It returns an array of information or null on a mismatch.
search String method that tests for a match in a string. It returns the index of the match, or -1 if the search fails.
replace String method that executes a search for a match in a string, and replaces the matched substring with a replacement substring.
split String method that uses a regular expression or a fixed string to break a string into an array of substrings.

c#

Ref: C# 正则表达式

匹配:匹配了以 'm' 开头以 'e' 结尾的单词

  1. using System;
  2. using System.Text.RegularExpressions;
  3.  
  4. namespace RegExApplication
  5. {
  6. class Program
  7. {
  8. private static void showMatch(string text, string expr)
  9. {
  10. Console.WriteLine("The Expression: " + expr);
  11. MatchCollection mc = Regex.Matches(text, expr);
  12. foreach (Match m in mc)
  13. {
  14. Console.WriteLine(m);
  15. }
  16. }
  17. static void Main(string[] args)
  18. {
  19. string str = "make maze and manage to measure it";
  20.  
  21. Console.WriteLine("Matching words start with 'm' and ends with 'e':");
  22. showMatch(str, @"\bm\S*e\b");
  23. Console.ReadKey();
  24. }
  25. }
  26. }

替换:替换掉多余的空格

  1. using System;
  2. using System.Text.RegularExpressions;
  3.  
  4. namespace RegExApplication
  5. {
  6. class Program
  7. {
  8. static void Main(string[] args)
  9. {
  10. string input = "Hello World ";
  11. string pattern = "\\s+";
  12. string replacement = " ";
  13. Regex rgx = new Regex(pattern);
  14. string result = rgx.Replace(input, replacement);
  15.  
  16. Console.WriteLine("Original String: {0}", input);
  17. Console.WriteLine("Replacement String: {0}", result);
  18. Console.ReadKey();
  19. }
  20. }
  21. }

数值的扩展

js

  1. 二进制和八进制表示法
  2. Number.isFinite(), Number.isNaN()
  3. Number.parseInt(), Number.parseFloat()
  4. Number.isInteger()
  5. Number.EPSILON  【Number.EPSILON实际上是 JavaScript 能够表示的最小精度】
  6. 安全整数和 Number.isSafeInteger()  【判断一个整数是否落在这个范围之内】
  7. Math 对象的扩展
  8. 指数运算符

c#

Ref: C#数学计算包 Math.NET

Ref: Math Class【MSDN】

函数的扩展

js

  • 函数的 length 属性
  1. (function (a) {}).length //
  2. (function (a = 5) {}).length //
  3. (function (a, b, c = 5) {}).length //

指定了默认值后,length属性将失真。

后文的 rest 参数也不会计入length属性

  1. (function(...args) {}).length //

  2. /**
    * 只计算最后一个有默认值参数之前的”未默认初始化“的参数的个数
    */
  3. (function (a = 0, b, c) {}).length //
  4. (function (a, b = 1, c) {}).length //
  • 作用域

例一:

  1. let x = 1;
  2.  
  3. function f(y = x) { # 调用函数f时,参数形成一个单独的作用域
  4. let x = 2; # 这一条语句 其实没用
  5. console.log(y);
  6. }
  7.  
  8. f() //

注意:参数中默认为是let,故锁住了作用域。

例二:

  1. let foo = 'outer';
  2.  
  3. function bar( func = () => foo ) {  // 同理,foo是外层的
  4. let foo = 'inner';
  5. console.log(func());
  6. }
  7.  
  8. bar(); // outer

例三:这里是三个作用域的x。

  1. var x = 1;
  2. function foo( x, y = function() { x = 2; } ) {  // 参数中的x是单独的作用域
  3. var x = 3; // 函数内部的x是另一个作用域  
  4. y(); // 执行y后,内部变量x和外部全局变量x的值都没变
  5. console.log(x);
  6. }
  7.  
  8. foo() //
  9. x //

这里,只有两个作用域,函数参数和函数内部的作用域是一样的。

  1. var x = 1;
  2. function foo(x, y = function() { x = 2; }) {
  3. x = 3;   // 内部变量x就指向第一个参数x
  4. y();
  5. console.log(x);
  6. }
  7.  
  8. foo() //
  9. x //
  • 应用

相当棒的tricky的方法:利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误。

一个不可以省略的参数:

一个可以省略的参数:

  1. function foo(optional = undefined) { ··· }
  • rest 参数

比过去的argument要好

  1. // arguments变量的写法
  2. function sortNumbers() {
  3. return Array.prototype.slice.call(arguments).sort();
  4. }
  5.  
  6. // arguments对象不是数组,而是一个类似数组的对象。
    // 所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。
  7.  
  8. -----------------------------------------------------------------------
  9.  
  10. // rest参数的写法
  11. const sortNumbers = (...numbers) => numbers.sort();
  12.  
  13. // rest 参数就不存在这个问题,它就是一个真正的数组,数组特有的方法都可以使用。

rest 参数必须在尾部

rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

  1. // 数组参数的典型用法
  2.  
  3. function push(array, ...items) {
  4. items.forEach(function(item) {
  5. array.push(item);
  6. console.log(item);
  7. });
  8. }
  9.  
  10. var a = [];
  11. push(a, 1, 2, 3)
  • 严格模式

只要参数使用了默认值、解构赋值、或者扩展运算符,就不能显式指定严格模式。

产生了矛盾点:"只有从函数体之中,才能知道参数是否应该以严格模式执行,但是参数却应该先于函数体执行"。

  1. // 报错
  2. function doSomething(value = 070) {
  3. 'use strict';  # 在执行这里前,如何处理参数是个问题
  4. return value;
  5. }

那干脆禁止掉就好了!

但并不是说,这跟‘严格模式’的初衷有冲突,两种方法可以规避这种限制。

第一种,是设定全局性的严格模式,这是合法的。

  1. 'use strict';
  2.  
  3. function doSomething(a, b = a) {
  4. // code
  5. }

第二种,是把函数包在一个无参数的立即执行函数里面。

  1. const doSomething = (function () {
  2. 'use strict';
  3. return function(value = 42) {
  4. return value;
  5. };
  6. }());

参考:[JS] Why "strict mode" here

  • name 属性
  1. const bar = function baz() {};
  2.  
  3. // ES5
  4. bar.name // "baz"
  5.  
  6. // ES6
  7. bar.name // "baz"

其他情况见原文。

  • 箭头函数

同样的,注意大括号(代码块) 是否作为了返回值。

  1. // 报错
  2. let getTempItem = id => { id: id, name: "Temp" };
  3.  
  4. // 不报错
  5. let getTempItem = id => ({ id: id, name: "Temp" });

    // 虽然可以运行,但会得到错误的结果
    // 由于引擎认为大括号是代码块,所以执行了一行语句a: 1
    // 这时,a可以被解释为语句的标签,因此实际执行的语句是1;
    // 然后函数就结束了,没有返回值。
    let foo = () => { a: 1 };
    foo() // undefined
  6. // 如果箭头函数只有一行语句,且不需要返回值,可以采用下面的写法,
    // 就不用写大括号了
    let fn = () => void doesNotReturn();

便捷一:箭头函数可以与变量解构结合使用。

  1. const full = ({ first, last }) => first + ' ' + last;

  2. // 等同于
  3. function full(person) {
  4. return person.first + ' ' + person.last;
  5. }

便捷二:简化回调函数。

  1. // 正常函数写法
  2. [1,2,3].map(function (x) {
  3. return x * x;
  4. });
  5.  
  6. // 箭头函数写法
  7. [1,2,3].map(x => x * x);

便捷三:与 rest 参数相结合。

  1. const numbers = (...nums) => nums;
  2. numbers(1, 2, 3, 4, 5)
  3. // [1,2,3,4,5]

  4. const headAndTail = (head, ...tail) => [head, tail];
  5. headAndTail(1, 2, 3, 4, 5)
  6. // [1,[2,3,4,5]]

箭头函数的使用注意点

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

this对象的指向是可变的;

但是在箭头函数中,它是固定的。

作用一

例子一:

  1. function foo() {
  2. setTimeout( () => {
  3. console.log('id:', this.id);
  4. }, 100 );
  5. }
  6.  
  7. var id = 21;
  8. // 对象{id:42}作为了参数
  9. foo.call({ id: 42 });
  10. // id: 42

例子二:

Timer函数内部设置了两个定时器,分别使用了箭头函数和普通函数。

前者的this绑定定义时所在的作用域(即Timer函数),

后者的this指向运行时所在的作用域(即全局对象)。

所以,3100 毫秒之后,timer.s1被更新了 3 次,而timer.s2一次都没更新。

作用二

箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。

注意:

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this

导致内部的this就是外层代码块的this。

除了this,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:argumentssupernew.target

  1. // ES6
  2. function foo() {
  3. setTimeout(() => {
  4. console.log('id:', this.id);
  5. }, 100);
  6. }
  7.  
  8. // ES5
  9. function foo() {
  10. var _this = this;
  11.  
  12. setTimeout(function () {
  13. console.log('id:', _this.id);
  14. }, 100);
  15. }

请问下面的代码之中有几个this

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)可以用 rest 参数,但不可以使用arguments对象,该对象在函数体内不存在。

(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

  • 嵌套的箭头函数

如下,可见箭头函数带来的好处,有点builder or pipeline的感觉。

  1. function insert(value) {
  2. return { into: function (array) {
  3. return { after: function (afterValue) {
  4. array.splice(array.indexOf(afterValue) + 1, 0, value);
  5. return array;
  6. }};
  7. }};
  8. }
  9.  
  10. insert(2).into([1, 3]).after(1); //[1, 2, 3]

上面这个函数,可以使用箭头函数改写。【记得加圆括号】

可读性提升,也可以采用下面的写法

  1. const plus1 = a => a + 1;
  2. const mult2 = a => a * 2;
  3.  
  4. mult2(plus1(5))
  5. //

箭头函数还有一个功能,就是可以很方便地改写 λ 演算。

【λ 演算】就是一种特殊的语法所书写的匿名函数。

参见:神奇的λ演算

  • call, apply

在原生js中会有三个很常见的函数,call, apply, bind。他们的作用就是改变当前函数的this指针。

Ref: 如何理解和熟练运用js中的call及apply?

-- 理论 --

当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作!

另外一个对象whiteDog = {food:"bone"},

我们不想对它重新定义say方法,我们可以通过call或apply用blackCat的say方法:blackCat.say.call(whiteDog)。

此时,say:function()中的this指针就成了whiteDog,this.food就变成了“bone”。

-- 实战 --

用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。
它不能应用Array下的push,pop等方法。我们可以通过:
  1. var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
这样domNodes就可以应用Array下的所有方法了。
  • 双冒号运算符

箭头函数可以绑定this对象,大大减少了显式绑定this对象的写法(callapplybind)。

但是,箭头函数并不适用于所有场合,所以现在有一个提案,提出了“函数绑定”(function bind)运算符,用来取代callapplybind调用。

【提案暂时不看】

  • 尾调用优化

尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

  1. function f(x) {
  2. if (x > 0) {
  3. return m(x)
  4. }
  5. return n(x);
  6. }

"尾调用"由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。

大大节省内存!

  1. function f() {
  2. let m = 1;
  3. let n = 2;
  4. return g(m + n);
  5. }
  6. f();
  7.  
  8. // 等同于
  9. function f() {
  10. return g(3);
  11. }
  12. f();
  13.  
  14. // 等同于
  15. g(3);

反例子:

  1. function addOne(a){
  2. var one = 1;
  3. function inner(b){
  4. return b + one;  // 因为这里,所以被迫在调用inner时还需要保留住var one,也就不是tail call了
  5. }
  6. return inner(a);
  7. }

NB: ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。

这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。

    • func.arguments:返回调用时函数的参数。
    • func.caller:返回调用当前函数的那个函数。

  • 尾递归

对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。  

  1. function factorial(n) {
  2. if (n === 1) return 1;
  3. return n * factorial(n - 1);
  4. }
  5.  
  6. factorial(5) // 120
  7.  
  8. --------------------------------------------------
    改写成尾递归,只保留一个调用记录,复杂度由O(n) --> O(1)
  1. function factorial(n, total) {
  2. if (n === 1) return total;
  3. return factorial(n - 1, n * total);
  4. }
  5. factorial(5, 1) // 120

可见,诀窍就在于:把所有用到的内部变量改写成函数的参数。

还有就是:只需要知道循环可以用递归代替,而一旦使用递归,就最好使用尾递归。

其他部分,柯里化(currying)【将多参数的函数转换成单参数的形式】详见链接。

尾递归优化只在严格模式下生效。

在正常模式下,或者那些不支持该功能的环境中,就是自己实现尾递归优化。

减少调用栈?就是采用“循环”换掉“递归”。

详见原链接。

  • 函数参数的尾逗号

ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。

这样的规定也使得,函数参数与数组和对象的尾逗号规则,保持一致了。

函数是一种对象

  • 到处都是”Object" 

基本值类型不是对象(number、string、Boolean、Undefined);

剩下的引用类型(函数、数组、null...)都是对象。

对象是通过函数创建的,而函数又是一种对象。那么这是为什么呢?这就牵扯到prototype原型。

[JS] ECMAScript 6 - String, Number, Function : compare with c#的更多相关文章

  1. js五种基本数据类型:string, number, boolean, null, undefined

    /** * 五种基本数据类型:string, number, boolean, null, undefined */ // undefined // 声明变量foo,未声明变量bar var foo; ...

  2. js基础篇string&&array(应YX同学面试复习要求 - -)

    js中的数据类型一共有五个基本数据类型,分别是undefined,null,boolean,number,string. js中的Object类型中包括两大类型:Function类型和array类型. ...

  3. Js对象转String的函数 和 JSON转String

    js对象转string的函数 function obj2str(o){ var r = []; if(typeof o =="string") return "" ...

  4. JS - 函数,Math,number

    函数分为:关键字function 匿名函数 — 没有名字的函数 有名函数 — 有名字的函数 <body> <div></div> <script> // ...

  5. js中关于string的一些常用的方法

    最近总结了一些关于string中的常用方法, 其中大部分的方法来自于<JavaScript框架设计>这本书, 如果有更好的方法,或者有关于string的别的常用的方法,希望大家不吝赐教. ...

  6. 小tips:JS数值之间的转换,JS中最大的Number是多少?,JS == 与 === 的区别

    JS数值之间的转换 Number(), parseInt(),parseFloat() Number()函数的转换规则如下: 1.如果boolean值,true和false将分别被转换为1和02.如果 ...

  7. JavaScript -- 时光流逝(三):js中的 String 对象的方法

    JavaScript -- 知识点回顾篇(三):js中的 String 对象的方法 (1) anchor(): 创建 HTML 锚. <script type="text/javasc ...

  8. js中的string.format

    String.prototype.format = function(args) { var result = this; if (arguments.length > 0) { if (arg ...

  9. js & array to string

    js & array to string https://stackoverflow.com/questions/13272406/convert-string-with-commas-to- ...

随机推荐

  1. 喵哈哈村的魔法考试 Round #20 (Div.2) 题解

    题解: A 喵哈哈村的跳棋比赛 题解:其实我们要理解题意就好了,画画图看看这个题意.x<y,那么就交换:x>y,那么x=x%y. 如果我们经过很多次,或者y<=0了,那么就会无限循环 ...

  2. linux中 判断变量中是否有给定元素

    grep find都是查找文件 所以shell编程时使用=~ 来进行变量中的匹配. 注意:if条件后面是两个[]. #!/bin/basha="abc.txt bde.txt ccc.txt ...

  3. mysql报错:1130 -host 'localhost' is not allowed to connect to this mysql server

    错误提示:1130 -host 'localhost' is not allowed to connect to this mysql server 原因:手贱把mysql数据库系统中mysql数据库 ...

  4. [原创]Java性能优化权威指南读书思维导图2

    [原创]Java性能优化权威指南读书思维导图2

  5. ArcGIS Pro 中不可用的工具

    有些可用于 ArcMap 之类的其他 ArcGIS Desktop 应用程序的地理处理工具在 ArcGIS Pro 中不可用.用于处理 ArcGIS Pro 所不支持的数据格式的地理处理工具已被移除, ...

  6. 奇怪吸引子---GenesioTesi

    奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...

  7. Mysql高效插入/更新数据

    从tushare抓取到的财务数据,最开始只是想存下来,用的办法想简单点,是:插入--报错-update 但发现这个方法太蠢,异常会导致大量无效连接,改为: for idx,row in d2.iter ...

  8. ls(ll)排序问题

    ls(ll)排序问题 1.按照时间倒叙排列—— -lnt ( LNT,大写备注区分一下) 2.安照时间正序排列—— -lrt (LRT) 3.按照文件名正序排序(默认的排序方式)—— -l 4.按照文 ...

  9. windows多线程--原子操作

    推荐参考博客:秒杀多线程第三篇 原子操作 Interlocked系列函数 原子操作 VS 非原子操作 原子操作就是不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程切 ...

  10. Git操作简单入门及相关命令

    说明:本文内容主要来自文末参考链接内容,此文仅作学习记录.如有转载,请到文末参考链接处. 1 基本概念理解 1.1 Git介绍 Git是分布式版本控制系统. 集中式VS分布式,SVN VS Git. ...