主要内容:
目录如下,右侧导航
- Javascript字符串
- 数组对象常用方法
- 正则表达式
- typeof
- 8/16进制
- Infinity/NaN
- 其他类型值转为boolean
- 优先级
- 预定义函数
- 变量提升
- 闭包
- call和apply
- 原型链
- 继承
- module
字符串对象
说明:下面RegExp/string的方法中,会自动将string传到reg(正则)的构造函数中转换成正则。
| 属性/方法 | 描述 |
|---|---|
length |
字符串长度。 |
charAt(n) |
返回在指定位置的字符。 |
substring(start, end) |
截取字符串的某一部分,返回的字符串要头不要尾[start,end)。第二个参数可选,默认[start,length)。 |
slice(start, end) |
与上面👆一样,能为负数更灵活。如果是负数,从尾部开始算起的位置。-1 指字符串的最后一个字符,-2 指倒数第二个字符,以此类推。 |
indexOf(string, n) |
要检索的字符串,第二个字符可选,规定从下标n开始。返回下标。 |
lastIndexOf(string,n) |
从后往前检索,用法与上面👆一致。返回下标。 |
match(string/reg) |
与上面两个👆👆类似。返回匹配结果的数组,数组的内容依赖于 RegExp 是否有全局标志 g。 |
search(string/reg) |
返回第一个与 regexp 相匹配的子串的起始位置。 |
replace(string/reg,replaceStr) |
只替换第一个!!!返回替换后的字符串。 |
split(string/reg,n) |
n可选,指定返回数组的最大长度。返回分割后的数组。 |
toLowerCase() |
转小写 |
toUpperCase() |
转大写 |
valueOf() |
返回对象的原始值,和toString方法会在一些情况下会自调用。应用 |
str.concat(string,…) |
必需,一个或多个。没什么鬼用,用+不是更好吗。 |
'haha'.split()
// ['haha']
'haha'.split('')
// ['h', 'a', 'h', 'a']
数组
不改变原数组的方法
- slice()---选取数组的的一部分,并返回一个新数组。
- join()---把数组的所有元素放入一个字符串。
- concat()---连接两个或更多的数组,并返回结果。
- map()---通过指定函数处理数组的每个元素,并返回处理后的数组。
- filter()---检测数组元素,并返回符合条件所有元素的数组。
- every()---检测数组元素的每个元素是否都符合条件。
- some()---检测数组元素中是否有元素符合指定条件。
- includes()---返回true或false。
- indexOf()---搜索数组中的元素,并返回它所在的位置。
- lastIndexOf()---返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
- valueOf()---返回数组对象的原始值。
- toString()---把数组转换为字符串,并返回结果
- find()---返回复合条件的第一个元素,后面的不再执行。没有符合条件的返回undefined
- find(function(currentValue, index, arr),thisValue)
改变原数组的方法
- pop()---删除数组的最后一个元素并返回删除的元素。
- push()---向数组的末尾添加一个或更多元素,并返回新的长度。
- shift()---删除并返回数组的第一个元素。
- unshift()---向数组的开头添加一个或更多元素,并返回新的长度。
- reverse()---反转数组的元素顺序。
- sort(func)---对数组的元素进行排序。按数字大小排序一定要写function
- splice()---用于插入、删除或替换数组的元素。
示例
var a = ['', 2, '2']
var res = a.every((value, index, arr) => {
if(!value)
console.log(index) // 0
console.log(a) // ['', 2, '2']
return !!value
})
res // false
var arr = [ "George", "John", "Thomas", "James", "Adrew", "Martin" ]
arr.splice(2,0,"William")
// George,John,William,Thomas,James,Adrew,Martin
正则表达式
| 符号 | 说明 | 例子 | 匹配的字符 |
|---|---|---|---|
^n |
开始 | /^1/ |
12\1\122 |
n$ |
结束 | /1$/ |
21\1\311 |
. |
一个任意字符 | /^a.a$/ |
aqa\asa |
[^nnnn] |
集合外的字符(单个) | /^[^123]$/ |
4\5\7 |
(reg|reg|reg) |
任意一个匹配 | /^(.|.a|1{2})$/ |
w\4a\11 |
i |
对大小写不敏感 | /^sad$/i |
Sad\sad\SAD |
g |
不是找到第一个就停 |
支持正则的string对象方法
- search
- replace
- split
- match
//search
'asddcada'.search(/.d/g) //1
'asddcada'.search(/.d/i) //1
//replace
'asddcada'.replace(/.d/i,' ') // 'a dcada'
'asddcada'.replace(/.d/g,' ') // 'a dc a'
//aplit
'asddcsda'.split(/.d/i) //['a', 'dc', 'a']
'asddcsda'.split(/.d/g) //['a', 'dc', 'a']
//match
'asddcsda'.match(/.d/i) //['sd', index: 1, input: 'asddcsda', groups: undefined]
'asddcsda'.match(/.d/g) //['sd', 'sd']
时间对象
| 方法 | 描述 |
|---|---|
| getFullYear() / setFullYear() | 获取年份 / 设置年月日 |
| getMonth() / setMonth() | 获取月份(0-11) / 设置月日 |
| getDate() / setDate() | 获取日数 / 可以设置日数 |
| getHours() getMinutes() getSeconds() setHours() setMinutes() setSecond() |
|
| getDay() | 获取今天星期几,返回数字0-6 0代表星期天 |
其他后续补充
typeof
可能返回的值:
- 'number'
- 'string'
- 'boolean'
- 'undefined'
- 'object'
- 'function'
typeof null // 'object'
// 如果a没有声明
typeof a // 'undefined'
但当你判断一个变量的类型时会遇到一些问题,如下例
var str1 = new String('js');
var str2 = 'js';
typeof str1; //object
typeof str2; //string
str1 instanceof String; //true
str2 instanceof String; //false
// typeof 用在一些通过new表达式生成的变量,输出为object
// instanceof 只能判断是否为Object、String、Array、Date等等或是用户通过构造函数自定义的类,而不能判断基本数据类型,基本数据类型不属于任何类
// 一个相对周全的办法
function isString(str){
return (typeof str == 'string')||(str instanceof String)
}
预定义函数
js引擎的一组可供随时调用的内建函数
- parseInt()
- parseFloat()
- isNaN()
- isFinite()
- encodeURI()
- decodeURI()
- encodeURIComponent()
- dncodeURIComponent()
- eval()
parseInt
parseInt('123') // 123
parseInt('a123') // NaN
parseInt('987', 8)
// NaN
parseInt('212', 8)
// 138
parseInt('212', 9)
// 173
// 0x开头会默认以16进制
parseInt('098')
// 98
parseInt('0377')
// 377
parseInt('0x377')
// 887
isNaN
isNaN('abv')
// true
isNaN(NaN)
// true
isNaN('1233m')
// true
isNaN('123')
isFinite
// 检查输入是否是一个既非Infinity也非NaN的数字
// 参数数字、数字字符串、null、true、false的时候
isFinite()
eval
// eval会将输入的字符串当做js代码来执行
eval('var li = 2;');
li
2
// eval可以用来深拷贝吗?
// 要考虑安全性和性能方面的问题
call & apply
这俩兄弟没啥区别,就是在传参数时,前者是平铺,后者是数组。 如果只传一个参数的话,就是代表指向的是这个参数,如果不想传第一个的话需要传一个null代表指向的是全局对象。
// 首先一个常用的用法是:用他们来触发函数
myfunc.call(this, ...args)
myfunc.apply(this, args)
// 第二个用法:利用他们来调用另一个对象的方法,据为己用
var obj = {
name: 'Judy',
say: function(who) {
return "Hello, "+ who + ", I'm " + this.name
}
}
obj.say('Tony')
// Hello, Tony, I'm Judy
var myObj = {name: 'Sam'}
obj.say.apply(myObj, ['Tony'])
obj.say.apply(myObj, 'Tony')
// Hello, Tony, I'm Sam
arguments 的特征只有数组的length属性
function func() {
var args = [].slice.call(arguments)
return args.reverse()
}
小数的处理
javascript进行科学计数法转换,保留有效位小数点(四舍五入/五舍六入/向下或向上取整)
四舍五入
Math.round('4.212'*100)/100 //4.21
Math.round('4.218'*100)/100 //4.22
五舍六入
toFixed()
2..toFixed(2) //2.00
2.3.toFixed(2) //2.30
2.31.toFixed(2) //2.31
2.31213.toFixed(2) //2.31
2.31567.toFixed(2) //2.31
2.3165.toFixed(2) //2.32
2.toFixed(2)
// Uncaught SyntaxError: Invalid or unexpected token
'2.21'.toFixed(2)
// Uncaught TypeError: "200.825".toFixed is not a function
-2..toFixed(2) //-2.00
-2.3.toFixed(2) //-2.30
...
// 下面一样
截取
巧用向下取整
Math.floor('4321'*100)/100 //4321
Math.floor('4.212'*100)/100 //4.21
Math.floor('4.218'*100)/100 //4.21
Math.floor(4321*100)/100 //4321
Math.floor(4.212*100)/100 //4.21
Math.floor(4.218*100)/100 //4.21
Math.floor('-4.218'*100)/100 //-4.22
Math.floor('-4.212'*100)/100 //-4.22
向上取整
Math.cell('-4.212'*100)/100 //-4.22
正则表达式(负数不行)
Number(15.7784514000.toString().match(/^\d+(?:\.\d{0,2})?/)) // 15.77
Number('15.7784514000'.toString().match(/^\d+(?:\.\d{0,2})?/)) // 15.77
Number('15.7'.toString().match(/^\d+(?:\.\d{0,2})?/)) // 15.7
Number('15'.toString().match(/^\d+(?:\.\d{0,2})?/)) // 15
丢掉小数部分
parseInt('-98.312'*2/2) // -98
parseInt('-98.912'*2/2) // -98
parseInt('-98.7766'*100)/100 // -98.77
8/16进制
// 0开头 就会把后面的当成8进制
let n = 0377
n // 255
n = -0377
n // -255
n = 097
n // 97
// 0x开头 就会吧后面的当成16进制
n = 0xff
n //255
进制转换见parseInt
其他类型值转为布尔为falsy的情况
// 为false的情况以下五种
!!''
!!null
!!undefined
!!0
!!NaN
// 注意这些'奇怪'的情况
NaN == NaN //false
!!Infinity //true
变量提升
先看以下代码,可能想当然的以为先alert(123),但其实并不是的。这里会有变量提升,虽然在第一个alert调用时,a没有在函数内被定义,但是变量本身已经存在于本地空间了,值为undefined并且覆盖了同名的全局变量。
var a = 123
function f() {
alert(a)
var a = 1
alert(a)
}
f()
闭包
利用闭包实现迭代器
function setup(x) {
var i = 0
return function() {
return x[i++]
}
}
var next = setup(['a', 'b', 'c'])
原型
__proto__与prototype的区别:
function Foo(){}
// Foo.prototype Foo的对象属性
// 当使用new Foo()来构造Foo的实例的时候,构造器的prototype属性会用做实例的原型 __proto__
[].__proto__ === Array.prototype
// true 即:实例的__proto__指向构造函数.prototype
Object.prototype.__proto__ === null
// true
// 注意:这里子对象.prototype.__proto__指向父对象.prototype
// 实例的__proto__指向构造函数.prototype
// 最内一层最终会指向Object.prototype,
// Object.prototype.__proto__指向null,结束链
继承
参考上面原型链的图学习下面代码
function Animal(){
this.animal = 'animal'
}
function Fish(){
this.fish = 'fish'
}
function SaltedFish(){
this.name = 'saltedFish'
}
SaltedFish.prototype = new Fish()
Fish.prototype = new Animal()
// 这里的SaltedFish并不能继承Animal因为,他是继承的Fish的实时实例
// 另外当我们对prototype完全替换时可能会对constructor属性产生副作用,我们需要对constructor进行重置
Fish.prototype.constructor = Fish
SaltedFish.prototype.constructor = SaltedFish
let sf = new SaltedFish()
sf.constructor === SaltedFish
SaltedFish.constructor === Function
// test
sf.__proto__ === SaltedFish.prototype
sf.__proto__.__proto__ === Fish.prototype
sf.__proto__.__proto__.__proto__ === Object.prototype
sf.__proto__.__proto__.__proto__.__proto__ === null
module
export
util.js
let a = 1
// 错误写法,相当于 export 1
export a
// 正确
export { a }
expert let b = 2
func.js
// 报错
import a from './util'
// 正确
import {a} from './util'
a // 1
import {a as aFunc} from './util'
aFunc // 1
a // undefined
import * as utils from './util'
utils.a // 1
import './util' // 会将util文件从头到尾执行一遍
export default
utils.js
export default function getUserName() {} // 输出
import getUserName from 'getUserName' // 输入
export function getUserName() {} // 输出
import {getUserName} from 'getUserName' // 输入