Function
Function 构造函数通过 new
创建一个新的 Function 对象。 在 JavaScript 中,每个函数实际上都是一个 Function 对象。
语法
构造函数
new Function ( [ argName1 [, argName1 [, argNameN... [, funcBody ]]]] )
函数类型转换函数
Function ( [ argName1 [, argName1 [, argNameN... [, funcBody ]]]] )
Function()
会把传入的最后一个参数作为函数定义的执行代码,之前的所有参数均依次作为函数定义的参数。
- 如果没有指定任何参数,则表示该函数没有定义参数列表,函数的执行代码也为空。
- 如果只指定了一个参数,则该参数将被视作函数的执行代码。如果你想定义一个参数、执行代码为空,请传入两个参数,第二个参数为空字符串即可:
new Function("argName1", "")
。
Function()
的返回值是 Function 类型,返回一个函数对象。
Function.prototype.apply
Function.prototype.apply
方法用于指定函数调用指向的 this
指针,并提供类数组类型的参数列表作为指定函数的参数。
语法
apply(thisArg: any, argArray?: any): any;
参数:
描述
Function.prototype.apply
与 Function.prototype.call
非常相似,不同之处在于提供参数的方式,apply
使用参数数组而非一组参数列表。
你可以使用 arguments 对象作为 argArray 参数。arguments 是一个函数的局部变量,它可以被用作被调用对象的所有未指定的参数。这样,你在使用 apply 方法时就不需要知道被调用的对象的所有参数。你可以使用 arguments 来把所有的参数传递给被调用对象。 被调用对象接下来就负责处理这些参数。
示例
数组元素添加
使用 Array.prototype.push
能将元素追加到数组中,并且,该方法可以接受可变数量的参数。
但是如果,我们需要传递一个数组追加到数组中,它实际上会将该数组作为单个元素添加,而不是单独添加元素,因此我们最终得到一个数组内的数组。
这种情况下,虽然可以通过 Array.prototype.concat
实现我们想要的行为,但它实际上不是附加到原有数组中,而是创建并返回新的数组。
而我们可以通过 Function.prototype.apply
实现该需求。
const foo = []; const bar = [1, 2, 3, 4]; foo.push.apply(foo, bar); console.log(foo); // [1, 2, 3, 4]
内置函数使用
可以使用 Function.prototype.apply
实现本来需要遍历数组变量的任务中使用内建的的函数。
以下例子使用 Math.max
和 Math.min
来找出一个数组中的最大 / 最小值。
const foo = [2, 4, 6, 8, 10]; const max = Math.max.apply(null, foo); const min = Math.min.apply(null, foo);
⚠️ 注意:使用上述方式调用 Function.prototype.apply,会有超出 JavaScript 引擎的参数长度限制的风险。当对一个函数传入非常多的参数(比如一万个)时,就非常有可能会导致越界问题,这个临界值是根据不同的 JavaScript 引擎而定的(JavaScript 核心中已经做了硬编码 参数个数限制在 65536),因为这个限制(实际上也是任何用到超大栈空间的行为的自然表现)是未指定的,有些引擎会抛出异常。更糟糕的是其他引擎会直接限制传入到方法的参数个数,导致参数丢失。
如果参数数组可能很大,可以使用以下策略处理:将参数数组切块后循环传入目标方法。
function minOfArray(arr) { var min = Infinity; var QUANTUM = 32768; for (var i = 0, len = arr.length; i < len; i += QUANTUM) { var submin = Math.min.apply(null, arr.slice(i, Math.min(i + QUANTUM, len))); min = Math.min(submin, min); } return min; } var min = minOfArray([5, 6, 2, 3, 7]);
Function.prototype.call
Function.prototype.call
方法用于指定函数调用指向的 this
指针,并分别提供参数作为指定函数的参数。
语法
语法:
call(thisArg: any, ...argArray: any[]): any;
参数
示例
function Product(name, price) { this.name = name; this.price = price; } function Food(name, price) { Product.call(this, name, price); this.category = 'food'; } function Toy(name, price) { Product.call(this, name, price); this.category = 'toy'; } const cheese = new Food('cheese', 5); const robot = new Toy('robot', 40); console.log(cheese); // { // category: "food", // name: "cheese", // price: 5, // } console.log(robot); // { // category: "toy", // name: "robot", // price: 40, // }
Function.prototype.bind
Function.prototype.bind
方法创建一个新函数,在 bind()
被调用时,这个新函数的 this
被指定为 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
语法
语法:
bind(thisArg: any, ...argArray: any[]): any; • 1
参数
描述
Function.prototype.bind 函数会创建一个新 绑定函数(Bound Function,BF)。绑定函数是一个 Exotic Function Object(怪异函数对象,ECMAScript 2015 中的术语),它包装了原函数对象。调用绑定函数通常会导致执行 包装函数。
绑定函数具有以下内部属性:
[[BoundTargetFunction]]
:包装的函数对象[[BoundThis]]
:在调用包装函数时始终作为this
值传递的值。[[BoundArguments]]
:列表,在对包装函数做任何调用都会优先用列表元素填充参数列表。[[Call]]
:执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是一个this
值和一个包含通过调用表达式传递给函数的参数的列表。
当调用绑定函数时,它调用 [[BoundTargetFunction]] 上的内部方法 [[Call]],就像这样 Call(boundThis, args)。其中,boundThis 是 [[BoundThis]],args 是 [[BoundArguments]] 加上通过函数调用传入的参数列表。
绑定函数也可以使用 new
运算符构造,它会表现为目标函数已经被构建完毕。提供的 this
值会被忽略,但前置参数仍会提供给模拟函数。
示例
创建绑定函数
Function.prototype.bind() 最简单的用法是创建一个函数,不论怎么调用,这个函数都有同样的 this 引用。JavaScript 新手经常犯的一个错误是将一个方法从对象中拿出来,然后再调用,期望方法中的 this 是原来的对象(比如在回调中传入这个方法)。如果不做特殊处理的话,一般会丢失原来的对象。基于这个函数,用原始的对象创建一个绑定函数,巧妙地解决了这个问题。
this.a = '100'; const foo = { a: '99', getA: function () { return this.a; }, }; foo.getA(); // '99' const retrieveA = foo.getA; retrieveA(); // '100' const boundGetA = retrieveA.bind(foo); boundGetA(); // '99'
偏函数
Function.prototype.bind() 方法的另一个最简单的用法是使一个函数拥有预设的初始参数。只要将这些参数(如果有的话)作为 bind() 的参数写在 this 后面。当绑定函数被调用时,这些参数会被插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们后面。
const foo = function (a, b, c, d, e, f) { console.log(a, b, c, d, e, f); }; // 预设三个参数 1 2 3 -> 对应 foo 参数 a b c const bar = foo.bind(null, 1, 2, 3); bar(4, 5, 6); // 1 2 3 4 5 6
配合定时器
默认情况下,使用 window.setTimeout 时,this
关键字会指向 Window 对象。当类的方法中需要 this
指向类的实例时,你可能需要显式地把 this
绑定到回调函数,就不会丢失该实例的引用。
function LaterBloomer() { this.petalCount = Math.ceil(Math.random() * 12) + 1; } LaterBloomer.prototype.bloom = function () { window.setTimeout(this.declare.bind(this), 1000); }; LateBloomer.prototype.declare = function () { console.log('I am a beautiful flower with ' + this.petalCount + ' petals!'); }; const flower = new LateBloomer(); flower.bloom();
String
String 对象是一个用于 字符串 或一个 字符序列 的构造函数。
String 对象是文本字符串的对象形式。String 对象允许操作和格式化文本字符串以及确定和定位字符串中的子字符串。
语法
构造函数
new String([value]);
字符串类型转换函数
String([value]);
说明
模板字面量
从 ECMAScript 2015 开始,字符串字面量也可以称为 模板字面量:
const w = 'world'`Hello ${w}!`;
String.fromCharCode
静态 String.fromCharCode()
方法返回由指定的 UTF-16 代码单元序列创建的字符串。
语法
String.fromCharCode(num1 [, num2 [, num3 ...[, numN]]]);
参数:
num
:一系列 UTF-16 代码单元的数字。范围介于 0 到 65535(0xFFFF
)之间。大于0xFFFF
的数字将被截断。不进行有效性检查。
使用示例
String.fromCharCode(65, 66, 67); // ABC String.fromCharCode(0x2014); // -
String.prototype.charAt()
charAt()
方法从一个字符串中返回指定的字符。
语法
str.charAt(index);
说明
字符串中的字符从左向右索引:
- 第一个字符的索引值为 0
- 最后一个字符(假设该字符位于字符串
stringName
中)的索引值为stringName.length - 1
- 如果指定的
index
值超出了该范围,则返回一个空字符串''
示例
const javascript = 'JAVASCRIPT'; javascript.charAt(); // J javascript.charAt(0); // J javascript.charAt(1); // A javascript.charAt(2); // V javascript.charAt(3); // A javascript.charAt(4); // S javascript.charAt(5); // C javascript.charAt(6); // R javascript.charAt(7); // I javascript.charAt(8); // P javascript.charAt(9); // T javascript.charAt(100); // ''
String.prototype.charCodeAt()
charCodeAt()
方法返回 0 到 65535 之间的整数,表示给定索引处的 UTF-16 代码单元(在 Unicode 编码单元表示一个单一的 UTF-16 编码单元的情况下,UTF-16 编码单元匹配 Unicode 编码单元。但在——例如 Unicode 编码单元 > 0x10000
的这种——不能被一个 UTF-16 编码单元单独表示的情况下,只能匹配 Unicode 代理对的第一个编码单元) 。如果你想要整个代码点的值,使用 codePointAt()
。
语法
str.charCodeAt(index);
返回值表示字符串对象指定索引处的字符的 Unicode 编码;如果索引超出范围,则返回 NaN
。
说明
Unicode 编码单元(code points)的范围从 0 到 1114111(0x10FFFF)。开头的 128 个 Unicode 编码单元和 ASCII 字符编码一样。
⚠️ 注意,charCodeAt 总是返回一个小于 65536 的值。这是因为高位编码单元(higher code point)使用一对(低位编码(lower valued))代理伪字符(“surrogate” pseudo-characters)来表示,从而构成一个真正的字符。因此,为了查看或复制(reproduce)65536 及以上编码字符的完整字符,需要在获取 charCodeAt(i) 的值的同时获取 charCodeAt(i+1) 的值,或者改为获取 codePointAt(i) 的值。
如果指定的 index 小于 0 或不小于字符串的长度,则 charCodeAt 返回 NaN。
示例
下例介绍了不同索引情况下返回的 Unicode 值:
'ABC'.charCodeAt(0); // 65 'ABC'.charCodeAt(1); // 66 'ABC'.charCodeAt(2); // 67 'ABC'.charCodeAt(3); // NaN
String.prototype.concat()
concat()
函数用于将当前字符串与指定字符串进行拼接,并返回拼接后的字符串。
语法
str.concat( string2, string3 [, ..., stringN] )
concat()
函数的返回值为 String
类型,其返回值为拼接后的字符串。
concat()
函数的作用等同于运算符 +
,例如:str.concat(str1, str2)
等同于 str + str1 + str2
。
说明
concat
方法将一个或多个字符串与原字符串连接合并,形成一个新的字符串并返回。 concat
方法并不影响原字符串。
示例
下面的例子演示如何将多个字符串与原字符串合并为一个新字符串
var hello = 'Hello, '; hello.concat('Kevin', ' have a nice day.'); // Hello, Kevin have a nice day.
建议使用赋值操作符(+
或 +=
)代替字符串的 concat
方法。
var hello = 'Hello, '; hello += 'world'; console.log(hello); // Hello, world
String.prototype.endsWith()
endsWith()
用来判断当前字符串是否是以另外一个给定的子字符串 结尾
的,根据判断结果返回 true
或 false
。
语法
str.endsWith( searchString [, length] )
这个方法帮助你确定一个字符串是否在另一个字符串的末尾。这个方法是大小写敏感的。
说明
concat
方法将一个或多个字符串与原字符串连接合并,形成一个新的字符串并返回。 concat
方法并不影响原字符串。
示例
const str = 'Hello world!'; console.log(str.endsWith('world!')); // true console.log(str.endsWith('abc')); // false
String.prototype.includes()
includes()
方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true
或 false
。
语法
str.includes( searchString [, startIndex] )
这个方法可以帮你判断一个字符串是否包含另外一个字符串。
这个方法搜索匹配的字符串是区分大小写的。
示例
var str = 'To be, or not to be, that is the question.'; console.log(str.includes('To be')); // true console.log(str.includes('question')); // true console.log(str.includes('nonexistent')); // false console.log(str.includes('To be', 1)); // false console.log(str.includes('TO BE')); // false
String.prototype.indexOf()
indexOf()
函数用于查找子字符串在当前字符串中第一次出现的位置。
语法
str.indexOf( searchValue[, startIndex])
indexOf() 方法的返回值为 Number 类型,返回子字符串在当前字符串中第一次查找到的起始位置(索引)。
示例
字符串中的字符被从左向右索引。首字符的索引(index)为 0,字符串 stringName 的最后一个字符的索引是 stringName.length - 1。
'Blue Whale'.indexOf('Blue'); // 0 'Blue Whale'.indexOf('Blute'); // -1 'Blue Whale'.indexOf('Whale', 0); // 5 'Blue Whale'.indexOf('Whale', 5); // 5 'Blue Whale'.indexOf('', 9); // 9 'Blue Whale'.indexOf('', 10); // 10 'Blue Whale'.indexOf('', 11); // 10
区分大小写
下例定义了两个字符串变量。
两个变量包含相同的字符串,除了第二个字符串中的某些字符为大写。第一个 log
方法输出 19。但是由于 indexOf
方法 区分大小写,因此不会在 myCapString
中发现字符串 “cheddar"
,结果第二个 log
方法输出 -1。
var myString = 'brie, pepper jack, cheddar'; var myCapString = 'Brie, Pepper Jack, Cheddar'; console.log('myString.indexOf("cheddar") is ' + myString.indexOf('cheddar')); // 19 console.log('myCapString.indexOf("cheddar") is ' + myCapString.indexOf('cheddar')); // -1
统计字符串中字母数量
使用 indexOf
统计一个字符串中某个字母出现的次数
在下例中,设置了 count
来记录字母 e 在字符串 str
中出现的次数:
let str = 'To be, or not to be, that is the question.'; let count = 0; let cur = str.indexOf('e'); // 当 cur 为 -1 时表示,字符串中已无检索子字符串 while (cur !== -1) { count++; cur = str.indexOf('e', cur + 1); } console.log(count); // displays 4
检测字符是否存在
当检测某个字符串是否存在于另一个字符串中时,可使用下面的方法:
'Blue Whale'.indexOf('Blue') !== -1; // true 'Blue Whale'.indexOf('Bloe') !== -1; // false
String.prototype.match()
match()
函数用于使用指定的正则表达式模式在当前字符串中进行匹配查找,并返回数组形式的查找结果。
语法
str.match(regexp);
💡 如果参数 regExp 不是正则表达式对象(RegExp),而是字符串类型,则 match() 先将该字符串传递给 RegExp 的构造函数,将其转换为一个 RegExp 对象。
match()方法的返回值为 Array 类型,其返回数组的成员取决于指定的正则表达式模式是否设有全局标志 g。
- 如果参数
regExp
没有全局标志g
,则match()
函数只查找第一个匹配,并返回包含查找结果的数组,该数组对象包含如下成员:
- 索引
0
:存放第一个匹配的子字符串。 - 属性
index
:匹配文本在字符串中的起始索引位置。 - 属性
input
:整个字符串对象(str
)。
在 IE 6 ~ IE 8 中,该数组还具有额外的 lastIndex
属性,用于存储匹配文本最后一个字符的下一个位置。
- 如果参数regExp设有全局标志g,则match()函数会查找所有的匹配,返回的数组不再有index和input属性,其中的数组元素就是所有匹配到的子字符串,形如:
- 索引 0:存放第一个匹配的子字符串(如果存在的话)。
- 索引 1:存放第二个匹配的子字符串(如果存在的话)。
- ......
- 索引 N-1:存放第 N 个匹配的字符串(如果存在的话)。
match()
函数如果没有查找到任何匹配,则返回null
。
说明
- 如果你需要知道一个字符串是否匹配一个正则表达式 RegExp ,可使用
String.prototype.search()
。 - 如果你只是需要第一个匹配结果,你可能想要使用
RegExp.prototype.exec()
。 - 如果你想要获得捕获组,并且设置了全局标志,你需要用
RegExp.prototype.exec()
。
示例
在下例中,使用 match 查找 "Hello world!"
紧跟着 1 个或多个数值字符,再紧跟着一个小数点和数值字符 0 次或多次。正则表达式包含 i
标志,因此大小写会被忽略。
var str = 'Hello world!'; str.match(); // ["", index: 0, input: "Hello world!", groups: undefined] str.match(/\b\w/); // ["H", "w"] str.match(/\w(?=r)/g); // null str.match(/\w[^\w]/g); // ["o", "d!"]
全局模式和不区分大小写模式
下例展示了 match()
使用 global
和 ignore case
标志。A-E
、a-e
的所有字母将会作为一个数组的元素返回。
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; var regexp = /[A-E]/gi; var matchArray = str.match(regexp); console.log(matchArray); // ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
不传参数
var str = 'Nothing will come of nothing.'; str.match(); // [""]
判断是否是微信浏览器
const isWeixin = function() { const ua = naviagtor.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) === 'micromessenger') { return true } else { return false; } }
String.prototype.replace()
replace()
函数用于使用指定字符串替换当前字符串中匹配指定正则表达式模式的子字符串,并返回完成替换后的字符串。
语法
str.replace(pattern, replacement);
一个部分或全部匹配由替代模式所取代的新的字符串。
描述
- 如果参数
pattern
是字符串,则replace()
函数将直接根据该字符串进行精确匹配,而不会试图转换为正则表达式,并且 只替换第一个匹配到 的子字符串 - 参数
replacement
可以使用以下以$
开头的 匹配变量 来动态确定用于替换的字符串内容(参数pattern
为正则表达式时才生效)
在进行全局的搜索替换时,正则表达式需包含 g
标志。
- 指定一个函数作为参数
你可以指定一个函数作为第二个参数。在这种情况下,当匹配执行后, 该函数就会执行。 函数的返回值作为替换字符串。(注意: 上面提到的特殊替换参数在这里不能被使用。) 另外要注意的是, 如果第一个参数是正则表达式, 并且其为全局匹配模式, 那么这个方法将被多次调用, 每次匹配都会被调用。
下面是该函数的参数:
精确的参数个数依赖于 replace()
的第一个参数是否是一个正则表达式对象, 以及这个正则表达式中指定了多少个括号子串。
示例
代码示例
在下面的例子中,replace()
中使用了正则表达式及忽略大小写标示。
var str = 'Twas the night before Xmas...'; var newstr = str.replace(/xmas/i, 'Christmas'); console.log(newstr); // Twas the night before Christmas... var str = 'Hello world!'; // 将字符 'lo' 替换为 '**' str.replace('lo', '**'); // "Hel** world!" // 将所有 'h' 替换为 '**'(全局,忽略大小写) str.replace(/h/ig); // '**ello world!' // 将位于单词边界前的两个字母替换为 '**' str.replace(/\w{2}\b/g, '**'); // "Hel** wor**!" // 将位于起始位置与单词边界的两个字母替换为 '**'(没有匹配项) str.replace(/^\w{2}\b/g/, '**'); // "Hello world!" // 在所有的连续两个字母并且后面不跟字母 'l' 的字母前添加 "**" // 这里的 "$1" 就表示正则表达式中第一个小括号内的子表达式匹配到的内容 str.replace(/(\w{2}(?!l))/g, '**$1'); // "He**llo **wo**rld!"
String.prototype.slice()
slice()
方法提取字符串的某部分,并返回一个新的字符串。
语法
str.slice( startIndex [, endIndex] )
返回一个从原字符串中提取出来的新字符串
描述
slice()
函数一直从索引 startIndex
复制到 endIndex
所指示的字符,但是不包括 endIndex
索引上的字符。
- 如果
startIndex
为负,则将其视为str.length + startIndex
。 - 如果省略
endIndex
,则将一直提取到字符串的结尾。 - 如果
endIndex
为负,则将其视为str.length + endIndex
。 - 如果
endIndex
小于等于startIndex
,则不会复制任何字符,返回空字符串。
示例
代码示例
var str = 'abcdefghij'; // 开始索引省略即从 0 开始提取,结束索引省略即提取到字符串末尾 str.slice(); // 'abcdefghij' // 开始索引为 0,结束索引省略即提取到字符串末尾 str.slice(0); // 'abcdefghij' // 开始索引为 0,结束索引为2 str.slice(0, 2); // 'ab' // 开始索引为 -3 即负数,即为 -3+10=7,结束索引省略即提取到字符串末尾 str.slice(-3); // 'hij' // 开始索引为 0,结束索引为 -3 即 -3+10=7 str.slice(0, -3); // 'abcdef' // 开始索引为 -3 即 -3+10=7,结束索引为 -1+10=9 str.slice(-3, -1);
String.prototype.split()
split()
函数用于使用指定分隔符分割字符串,并返回分割后的若干个子字符串组成的数组。
语法
str.split( [separator [, limit]] )
- 找到分隔符后,将其从字符串中删除,并将子字符串的数组返回。
- 如果没有找到或者省略了分隔符,则该数组包含一个由整个字符串组成的元素。
- 如果分隔符为空字符串,则字符串会在每个字符之间分割。
- 如果分隔符出现在字符串的开始或结尾,或两者都分开,分别以空字符串开头,结尾或两者开始和结束。因此,如果字符串仅由一个分隔符实例组成,则该数组由两个空字符串组成。
- 如果分隔符是包含捕获括号的正则表达式,则每次分隔符匹配时,捕获括号的结果(包括任何未定义的结果)将被拼接到输出数组中。但是,并不是所有浏览器都支持此功能。
- 当被查找的字符串为空时,返回一个包含一个空字符串的数组,而不是一个空数组,如果字符串和分隔符都是空字符串,则返回一个空数组。
描述
如果提供了 limit
参数,此函数返回的数组最多包含 limit
个元素。如果参数 limit
为负数,则该参数将被忽略掉。如果省略了 limit
,则 split()
函数不会考虑长度,直到分割完毕为止。如果 limit
为 0,则返回空的数组。
示例
代码示例
'abcd'.split(); // ["abcd"] 'abcd'.split('b'); // ["a", "cd"] 'abcd'.split('a'); // ["", "bcd"] 'abcd'.split('d'); // ["abc", ""] 'abcd'.split('abcd'); // ["", ""] 'abcd'.split(''); // ["a", "b", "c", "d"] 'abcd'.split(' '); // ["abcd"] ''.split(); // [""] ''.split(''); // [] ''.split(' '); // [""]
String.prototype.toLowerCase()
toLowerCase()
函数用于将当前字符串的所有字母转为小写,并返回转换后的字符串。该函数基于常规的 Unicode 大小写映射进行转换。
语法
str.toLowerCase();
描述
toLowerCase
将调用该方法的字符串值转换为小写形式,并返回。toLowerCase()
方法不影响字符串本身的值,返回的是新的字符串。
示例
var abc = 'ABC'; abc.toLowerCase(); // 'abc'
String.prototype.toUpperCase()
toUpperCase()
函数用于将当前字符串中的所有字母转为大写,并返回转换后的字符串。该函数基于常规的 Unicode 大小写映射进行转换。
语法
str.toUpperCase();
描述
toUpperCase
将调用该方法的字符串值转换为大写形式,并返回。toUpperCase
方法不影响字符串本身的值,返回的是新的字符串。
示例
var abc = 'abc'; abc.toUpperCase(); // 'ABC'