在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
字符串的扩展js
Ref: 模板字符串 策略:${var},放在反引号中! 通过tag来表示字符串。 使用for输出完整的字符串,记得最后一个strings[strings.length-1]。
c# Ref: 一个非常好的C#字符串操作处理类StringHelper.cs 字符串(C# 编程指南) 常用C#字符串函数大全
正则表达式的扩展js 修饰符:
var urlReg = /(\w+):\/\/([\w.]+)\/(\S*)/; var myHomepage = "http://www.wanjilong.com/homepage"; var result = myHomepage.match(urlReg);
Ref: JavaScript 正则表达式 Ref: JavaScript RegExp 对象 var patt = new RegExp(pattern,modifiers); 或者,更简单的方法 var patt = /pattern/modifiers; test():一个字符串是否匹配某个模式 exec():检索字符串中的正则表达式的匹配
c# Ref: C# 正则表达式 匹配:匹配了以 'm' 开头以 'e' 结尾的单词 using System; using System.Text.RegularExpressions; namespace RegExApplication { class Program { private static void showMatch(string text, string expr) { Console.WriteLine("The Expression: " + expr); MatchCollection mc = Regex.Matches(text, expr); foreach (Match m in mc) { Console.WriteLine(m); } } static void Main(string[] args) { string str = "make maze and manage to measure it"; Console.WriteLine("Matching words start with 'm' and ends with 'e':"); showMatch(str, @"\bm\S*e\b"); Console.ReadKey(); } } } 替换:替换掉多余的空格 using System; using System.Text.RegularExpressions; namespace RegExApplication { class Program { static void Main(string[] args) { string input = "Hello World "; string pattern = "\\s+"; string replacement = " "; Regex rgx = new Regex(pattern); string result = rgx.Replace(input, replacement); Console.WriteLine("Original String: {0}", input); Console.WriteLine("Replacement String: {0}", result); Console.ReadKey(); } } }
数值的扩展js
c# Ref: C#数学计算包 Math.NET Ref: Math Class【MSDN】
函数的扩展js
(function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2
指定了默认值后, 后文的 rest 参数也不会计入 (function(...args) {}).length // 0
例一: let x = 1;
function f(y = x) { # 调用函数
注意:参数中默认为是let,故锁住了作用域。 例二: let foo = 'outer'; function bar( func = () => foo ) { // 同理,foo是外层的 let foo = 'inner'; console.log(func()); } bar(); // outer
例三:这里是三个作用域的x。 var x = 1; 这里,只有两个作用域,函数参数和函数内部的作用域是一样的。 var x = 1; function foo(x, y = function() { x = 2; }) { x = 3; // 内部变量
相当棒的tricky的方法:利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误。 一个不可以省略的参数: 一个可以省略的参数: function foo(optional = undefined) { ··· }
比过去的argument要好 // arguments变量的写法 function sortNumbers() { return Array.prototype.slice.call(arguments).sort(); }
rest 参数必须在尾部 rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。 // 数组参数的典型用法
只要参数使用了默认值、解构赋值、或者扩展运算符,就不能显式指定严格模式。 产生了矛盾点:"只有从函数体之中,才能知道参数是否应该以严格模式执行,但是参数却应该先于函数体执行"。 // 报错 function doSomething(value = 070) { 'use strict'; # 在执行这里前,如何处理参数是个问题 return value; } 那干脆禁止掉就好了!
但并不是说,这跟‘严格模式’的初衷有冲突,两种方法可以规避这种限制。 第一种,是设定全局性的严格模式,这是合法的。 'use strict'; function doSomething(a, b = a) { // code } 第二种,是把函数包在一个无参数的立即执行函数里面。 const doSomething = (function () { 'use strict'; return function(value = 42) { return value; }; }());
const bar = function baz() {}; // ES5 bar.name // "baz" // ES6 bar.name // "baz" 其他情况见原文。
同样的,注意大括号(代码块) 是否作为了返回值。 // 报错 let getTempItem = id => { id: id, name: "Temp" }; // 不报错 let getTempItem = id => ({ id: id, name: "Temp" });
便捷一:箭头函数可以与变量解构结合使用。 const full = ({ first, last }) => first + ' ' + last; 便捷二:简化回调函数。 // 正常函数写法 [1,2,3].map(function (x) { return x * x; }); // 箭头函数写法 [1,2,3].map(x => x * x); 便捷三:与 rest 参数相结合。 const numbers = (...nums) => nums; numbers(1, 2, 3, 4, 5) // [1,2,3,4,5]
箭头函数的使用注意点 (1)函数体内的
但是在箭头函数中,它是固定的。 作用一 例子一: function foo() { setTimeout( () => { console.log('id:', this.id); }, 100 ); } var id = 21; // 对象{id:42}作为了参数 foo.call({ id: 42 }); // id: 42 例子二:
前者的 后者的 所以,3100 毫秒之后,
作用二 箭头函数可以让 注意:
导致内部的 除了 // ES6 function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } // ES5 function foo() { var _this = this; setTimeout(function () { console.log('id:', _this.id); }, 100); } 请问下面的代码之中有几个
(2)不可以当作构造函数,也就是说,不可以使用 (3)可以用 rest 参数,但不可以使用 (4)不可以使用
如下,可见箭头函数带来的好处,有点builder or pipeline的感觉。 function insert(value) { return { into: function (array) { return { after: function (afterValue) { array.splice(array.indexOf(afterValue) + 1, 0, value); return array; }}; }}; } insert(2).into([1, 3]).after(1); //[1, 2, 3] 上面这个函数,可以使用箭头函数改写。【记得加圆括号】 可读性提升,也可以采用下面的写法 const plus1 = a => a + 1; const mult2 = a => a * 2; mult2(plus1(5)) // 12
箭头函数还有一个功能,就是可以很方便地改写 λ 演算。 【λ 演算】就是一种特殊的语法所书写的匿名函数。 参见:神奇的λ演算
在原生js中会有三个很常见的函数,call, apply, bind。他们的作用就是改变当前函数的this指针。 -- 理论 -- 当一个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等方法。我们可以通过:
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
这样domNodes就可以应用Array下的所有方法了。
箭头函数可以绑定 但是,箭头函数并不适用于所有场合,所以现在有一个提案,提出了“函数绑定”(function bind)运算符,用来取代 【提案暂时不看】
尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。 function f(x) { if (x > 0) { return m(x) } return n(x); }
"尾调用"由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。 大大节省内存! function f() { let m = 1; let n = 2; return g(m + n); } f(); // 等同于 function f() { return g(3); } f(); // 等同于 g(3); 反例子: function addOne(a){ var one = 1; function inner(b){ return b + one; // 因为这里,所以被迫在调用inner时还需要保留住var one,也就不是tail call了 } return inner(a); }
NB: ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。 这是因为在正常模式下,函数内部有两个变量,可以跟踪函数的调用栈。
对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。 function factorial(n) { if (n === 1) return 1; return n * factorial(n - 1); } factorial(5) // 120
可见,诀窍就在于:把所有用到的内部变量改写成函数的参数。 还有就是:只需要知道循环可以用递归代替,而一旦使用递归,就最好使用尾递归。 其他部分,柯里化(currying)【将多参数的函数转换成单参数的形式】详见链接。
尾递归优化只在严格模式下生效。 在正常模式下,或者那些不支持该功能的环境中,就是自己实现尾递归优化。 减少调用栈?就是采用“循环”换掉“递归”。 详见原链接。
ES2017 允许函数的最后一个参数有尾逗号(trailing comma)。 这样的规定也使得,函数参数与数组和对象的尾逗号规则,保持一致了。
函数是一种对象
基本值类型不是对象(number、string、Boolean、Undefined); 剩下的引用类型(函数、数组、null...)都是对象。
对象是通过函数创建的,而函数又是一种对象。那么这是为什么呢?这就牵扯到prototype原型。
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论