我们要讲什么
- ECMAScript 基础对象(Object、Boolean、Number、String)
- 常用内置对象(Date、Array、Math、RegExp、global、Function、Event、arguments、JSON)
- ECMAScript 函数(声明、调用、返回值、闭包、递归)
ECMAScript 基础对象
在 ECMAScript 中,所有对象并非同等创建的。
一般来说,可以创建并使用的对象有三种:本地对象、内置对象和宿主对象。
ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。
简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。它们包括:Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIErrorECMA-262 把内置对象(built-in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。
ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。所有非本地对象都是宿主对象(host object),即由 ECMAScript 实现的宿主环境提供的对象。所有 BOM 和 DOM 对象都是宿主对象。
Object 对象
Object 是所有对象的基础。JavaScript 中的所有对象都来自 Object ;所有对象从 Object.prototype 继承方法和属性,尽管它们可能被覆盖。
例如,其他构造函数的原型将覆盖 constructor 属性并提供自己的 toString() 方法。Object 原型对象的更改将传播到所有对象,除非受到这些更改的属性和方法将沿原型链进一步覆盖。
类型 | key | 用法 | 作用 |
属性 | length | Object.length | Object.length 值为1 |
属性 | prototype | Object.prototype | 可以为所有 Object 类型的对象添加属性 |
方法 | assign | Object.assign() | 通过复制一个或多个对象来创建一个新的对象 |
方法 | create | Object.create() | 使用指定的原型对象和属性创建一个新对象 |
方法 | defineProperty | Object.defineProperty() | 给对象添加一个属性并指定该属性的配置 |
方法 | defineProperties | Object.defineProperties() | 给对象添加多个属性并分别指定它们的配置 |
方法 | entries | Object.entries() | 返回给定对象自身可枚举属性的[key, value]数组 |
方法 | freeze | Object.freeze() | 冻结对象:其他代码不能删除或更改任何属性 |
方法 | getOwnPropertyDescriptor | Object.getOwnPropertyDescriptor() | 返回对象指定的属性配置 |
方法 | getOwnPropertyNames | Object.getOwnPropertyNames() | 返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名 |
方法 | getOwnPropertySymbols | Object.getOwnPropertySymbols() | 返回一个数组,它包含了指定对象自身所有的符号属性 |
方法 | getPrototypeOf | Object.getPrototypeOf() | 返回指定对象的原型对象 |
方法 | is | Object.is() | 比较两个值是否相同。所有 NaN 值都相等(这与==和===不同) |
方法 | isExtensible | Object.isExtensible() | 判断对象是否可扩展 |
方法 | isFrozen | Object.isFrozen() | 判断对象是否已经冻结 |
方法 | isSealed | Object.isSealed() | 判断对象是否已经密封 |
方法 | keys | Object.keys() | 返回一个包含所有给定对象自身可枚举属性名称的数组 |
方法 | preventExtensions | Object.preventExtensions() | 防止对象的任何扩展 |
方法 | seal | Object.seal() | 防止其他代码删除对象的属性 |
方法 | setPrototypeOf | Object.setPrototypeOf() | 设置对象的原型(即内部[[Prototype]]属性) |
方法 | values | Object.values() | 返回给定对象自身可枚举值的数组 |
原型属性 | ([]).constructor === Array | Object.prototype.constructor | 特定的函数,用于创建一个对象的原型 |
原型属性 | ([]).__proto__ === Array.prototype | Object.prototype.__proto__ | 指向当对象被实例化的时候,用作原型的对象 |
原型方法 | Object.prototype.hasOwnProperty() | 返回一个布尔值 ,表示某个对象是否含有指定的属性,而且此属性非原型链继承的 | |
原型方法 | Object.prototype.isPrototypeOf() | 返回一个布尔值,表示指定的对象是否在本对象的原型链中 | |
原型方法 | Object.prototype.propertyIsEnumerable() | 判断指定属性是否可枚举 | |
原型方法 | Object.prototype.toLocaleString() | 直接调用 toString()方法 | |
原型方法 | Object.prototype.toString() | 返回对象的字符串表示 | |
原型方法 | Object.prototype.valueOf() | 返回指定对象的原始值 |
Boolean 对象
这个对象非常的简单。只有从Object哪里基础来的方法和属性。当做函数调用,就是把值转换成布尔类型
如果第一个参数不是布尔值,则会将其转换为布尔值。如果省略该参数,或者其值为 0、-0、null、false、NaN、undefined、或者空字符串(""),则生成的 Boolean 对象的值为 false。如果传入的参数是 DOM 对象 document.all,也会生成值为 false 的 Boolean 对象。
任何其他的值,包括值为 "false" 的字符串和任何对象,都会创建一个值为 true 的 Boolean 对象。注意不要将基本类型中的布尔值 true 和 false 与值为 true 和 false 的 Boolean 对象弄混了。
当 Boolean 对象用于条件语句的时候(译注:意为直接应用于条件语句),任何不是 undefined 和 null 的对象,包括值为 false 的 Boolean 对象,都会被当做 true 来对待。例如,下面 if 语句中的条件为真:
var x = new Boolean(false); if (x) { console.log(typeof x, typeof true, typeof false) }
Number 对象
类型 | key | 用法 | 作用 |
属性 | EPSILON | Number.EPSILON | 两个可表示(representable)数之间的最小间隔 |
属性 | MAX_SAFE_INTEGER | Number.MAX_SAFE_INTEGER | JavaScript 中最大的安全整数 (253 - 1) |
属性 | MAX_VALUE | Number.MAX_VALUE | 能表示的最大正数。最小的负数是 -MAX_VALUE |
属性 | MIN_SAFE_INTEGER | Number.MIN_SAFE_INTEGER | JavaScript 中最小的安全整数 (-(253 - 1)) |
属性 | MIN_VALUE | Number.MIN_VALUE | 能表示的最小正数即最接近 0 的正数 (实际上不会变成 0)。最大的负数是 -MIN_VALUE |
属性 | NaN | Number.NaN | 特殊的“非数字”值 |
属性 | NEGATIVE_INFINITY | Number.NEGATIVE_INFINITY | 特殊的负无穷大值,在溢出时返回该值 |
属性 | POSITIVE_INFINITY | Number.POSITIVE_INFINITY | 特殊的正无穷大值,在溢出时返回改值 |
属性 | prototype | Number.prototype | Number 对象上允许的额外属性 |
方法 | isNaN | Number.isNaN() | 确定传递的值是否是 NaN |
方法 | isFinite | Number.isFinite() | 确定传递的值类型及本身是否是有限数 |
方法 | isInteger | Number.isInteger() | 确定传递的值类型是“number”,且是整数 |
方法 | isSafeInteger | Number.isSafeInteger() | 确定传递的值是否为安全整数 ( -(253 - 1) 至 253 - 1之间) |
方法 | toInteger | Number.toInteger() | 计算传递的值并将其转换为整数 (或无穷大) |
方法 | parseFloat | Number.parseFloat() | 和全局对象 parseFloat() 一样 |
方法 | parseInt | Number.parseInt() | 和全局对象 parseInt() 一样 |
原型方法 | toExponential | Number.prototype.toExponential() | 返回以科学计数法表示的数字字符串 |
原型方法 | toFixed | Number.prototype.toFixed() | 返回固定小数位的数字字符串(四拾伍入) |
原型方法 | toLocaleString | Number.prototype.toLocaleString() | 返回以本地语言为主的数字字符串。会覆盖 Object.prototype.toLocaleString()。 |
原型方法 | toPrecision | Number.prototype.toPrecision() | 返回固定位数表示的数字字符串(小数点不记位,四拾伍入、位数不够会返回科学计数法) |
原型方法 | toString | Number.prototype.toString() | 返回以指定基数表示的数字字符串。会覆盖 Object.prototype.toString() |
原型方法 | valueOf | Number.prototype.valueOf() | 返回以原始数值。会覆盖 Object.prototype.valueOf() |
String 对象
类型 | key | 用法 | 作用 |
属性 | length | ''.length | 返回文字长度 |
方法 | String.fromCharCode() | String.fromCharCode(97) == 'A' | 通过 一系列UTF-16代码单元的数字。 范围介于0到65535(0xFFFF)之间。 大于0xFFFF的数字将被截断。 不进行有效性检查。 创建字符串 |
方法 | String.fromCodePoint() | String.fromCodePoint(65,97) == 'Aa' | 通过Unicode创建字符串 |
原型方法 | charAt() | '李li'.charAt(1) == 'l' | 返回特定位置的字符 |
原型方法 | charCodeAt() | '李li'.charCodeAt(0) == 26446 | 返回表示给定索引的字符的Unicode的值 |
原型方法 | codePointAt() | '李li'.codePointAt(0) == 26446 | 返回表示给定索引的字符的Unicode的值 |
原型方法 | concat() | 'l'.concat('i') == 'li' | 连接两个字符串文本,并返回一个新的字符串 |
原型方法 | includes() | 'li'.includes('i') | 判断一个字符串里是否包含其他字符串 |
原型方法 | endsWith() | 'li'.endsWith('i') | 判断一个字符串的结尾是否包含其他字符串中的字符 |
原型方法 | indexOf() | 'li'.indexOf('i') | 从字符串对象中返回首个被发现的给定值的索引值,如果没有找到则返回-1 |
原型方法 | lastIndexOf() | 'li'.lastIndexOf('i') | 从字符串对象中返回最后一个被发现的给定值的索引值,如果没有找到则返回-1 |
原型方法 | localeCompare() | 返回一个数字表示是否引用字符串在排序中位于比较字符串的前面,后面,或者二者相同 | |
原型方法 | match() | 'onmousemove'.match(/on(w+)/) | 使用正则表达式与字符串相比较 |
原型方法 | normalize() | 返回调用字符串值的Unicode标准化形式 | |
原型方法 | padEnd() | '1'.padEnd(5, ' ') | 在当前字符串尾部填充指定的字符串, 直到达到指定的长度。 返回一个新的字符串 |
原型方法 | padStart() | '1'.padStart(5, '0') | 在当前字符串头部填充指定的字符串, 直到达到指定的长度。 返回一个新的字符串 |
原型方法 | repeat() | '*'.repeat(10) | 返回指定重复次数的由元素组成的字符串对象 |
原型方法 | replace() | '李?'.replace('?','**') | 被用来在正则表达式和字符串直接比较,然后用新的子串来替换被匹配的子串 |
原型方法 | search() | '李?'.search('?') | 对正则表达式和指定字符串进行匹配搜索,返回第一个出现的匹配项的下标 |
原型方法 | slice() | "李**".slice(0,2) | 摘取一个字符串区域,返回一个新的字符串 |
原型方法 | split() | 'a,b,123,f'.split(',') | 通过分离字符串成字串,将字符串对象分割成字符串数组 |
原型方法 | startsWith() | 判断字符串的起始位置是否匹配其他字符串中的字符 | |
原型方法 | substr() | 通过指定字符数返回在指定位置开始的字符串中的字符 | |
原型方法 | substring() | 返回在字符串中指定两个下标之间的字符 | |
原型方法 | toLocaleLowerCase() | 根据当前区域设置,将符串中的字符转换成小写。对于大多数语言来说,toLowerCase的返回值是一致的 | |
原型方法 | toLocaleUpperCase() | 根据当前区域设置,将字符串中的字符转换成大写,对于大多数语言来说,toUpperCase的返回值是一致的 | |
原型方法 | toLowerCase() | 将字符串转换成小写并返回 | |
原型方法 | toSource() | 返回一个对象文字代表着特定的对象。你可以使用这个返回值来创建新的对象。重写 Object.prototype.toSource 方法 | |
原型方法 | toString() | 返回用字符串表示的特定对象。重写 Object.prototype.toString 方法 | |
原型方法 | toUpperCase() | 将字符串转换成大写并返回 | |
原型方法 | trim() | ' 1 '.trim() |
从字符串的开始和结尾去除空格。参照部分 ECMAScript 5 标准 |
原型方法 | trimStart()trimLeft() | ' 1 '.trimStart() |
从字符串的左侧去除空格 |
原型方法 | trimEnd()trimRight() | ' 1 '.trimEnd() |
从字符串的右侧去除空格 |
原型方法 | valueOf() | 返回特定对象的原始值。重写 Object.prototype.valueOf 方法 |
常用内置对象
这个我就直接说常用的了。
Date
Date 对象是自1970年1月1日(UTC)起经过的毫秒数。
- 实例化方式
newDate();//当前时间
newDate(Number);//传入的毫秒数转换成时间
newDate(dateString);//传入的时间格式转换为时间。这里有一些坑(低版本IE、ios、chrome)实现的规范不一样,导致有的格式解析不出来,可以用[momentjs][3]。
newDate(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
注意:只能将 Date 作为构造函数调用,才能实例化(instantiate) Date 对象:若将它作为常规函数调用(即不加 new 操作符),则将会返回一个字符串,而非 Date 对象。另外,不像其他的 JavaScript 对象类型,Date 对象没有字面量语法(literal syntax)。
- 方法
a.Date.now()
返回自 1970-1-1 00:00:00 UTC(世界标准时间)至今所经过的毫秒数。
等效写法+new Date()
,new Date().getTime()
b.Date.parse()
解析一个表示日期的字符串,并返回从 1970-1-1 00:00:00 所经过的毫秒数。
c.Date.UTC()
接受和构造函数最长形式的参数相同的参数(从2到7),并返回从 1970-01-01 00:00:00 UTC 开始所经过的毫秒数。
- 原型方法
a.getDay()
周,getFullYear()
年,getMonth()
月,getDate()
日,getHours()
时,getMinutes()
分,getSeconds()
秒
b.getTimezoneOffset()
返回当前时区的时区偏移。
c.set方法同上,需要注意的地方有setHours()
可以把时分秒毫秒都设置了
Array
join
合并成串
concat
合并其他数组
slice
分割数组
Math
Math.random()
随机数。来个公式(end-start+1)*num+start
比如 60-90区间内(90-60+1)*Math.random()+60>>0
即可得到区间内整数
Math.ceil
向上取整Math.ceil(5.1)
Math.floor
向下取整Math.floor(1.9)
Math.round
四拾伍入Math.round(2.3)
Math.pow
Math.pow(3,5)
等同于3**5
,但是前者兼容更好
RegExp
原生的方法其实很少用。需要注意的地方是,有部分函数会记录上次差到的点。一般都是用字符串的 replace
和 match
JSON
低版本 IE 没有。需要使用 eval
。
提供了 JSON.stringify
和 JSON.parse()
用来序列化与反序列化
//提供一个tips,你可以在控制台试试哟。 JSON.stringify([{ userid: 7848950, nickname: 'abc' },{ userid: 920110633, nickname: 'abc' },{ userid: 7848952, nickname: 'abc' }], null, ' ')
ECMAScript 函数(声明、调用、返回值、闭包、递归)
函数声明
- 函数声明
function fun(){}
- 函数表达式
fun = function fun(){}
- IFFE
void function(){console.log(1)}()
- 构造函数
new Function('a','b','return a+b')(1,2)
函数调用
function fun(){console.log(1)};fun()
通过括号来调用
返回值
function fun(){return 1};console.log(fun())
函数内部通过return
来返回
闭包
- 什么是作用域
作用域(scope)指的是变量存在的范围。 在 es5 中的,Javascript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。(es6中又新增了块级作用域)全局作用域可以在代码的任何地方都能被访问。
- 什么是作用域链
是指作用域生成的路径。当代码在一个执行环境中执行时,就会创建一个作用域链。我们有可能两个 function
内都使用了 state
这个变量,我们不希望他共享,他被限制在了自己的作用域中。
内部环境可以通过作用域链访问所有外部环境,但是外部环境不能访问内部环境中的任何变量和函数。
在 js 中与作用域链相似的有原型链
- 那么什么是闭包呢?
闭包就是依赖这个特性,思考如下代码。可以让我们的代码和外部环境隔离。
var getNum = (function(){ var sum = 0;//闭包中的变量 return function(){ return ++sum//内部可以访问 } })() getNum();//1,这里可以获取调用次数 sum = 1000;//这里改变的其实是全局的,因为他拿不到闭包内的sum getNum();//2,这里可以获取调用次数
回调函数
有的教程里面叫高阶函数,思考如下代码
[1,2,3].map(v=>v*2);//map就是一个高阶函数,通过把回调传递进去。对原数组进行操作。
递归函数
这个主要是用来没有预期的情况。比如遍历一颗树。你不知道要循环多少次。或者说当前有个dom节点,你需要找到他的一个父级.editor_main
。
//求菲波那切数列 function factorial(num){ if(num <= 1){ return 1 }else { return num * factorial(num - 1); } }