前端培训-初级阶段(13) - ECMAScript (内置对象、函数)

前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。

该文为前端培训-初级阶段(13、18)的补充内容 (介绍了 ECMAScript 历史,ES6 常用点)。

本文介绍ECMAScript基础知识

  1. 前端培训-初级阶段(13) - ECMAScript (语法、变量、值、类型、运算符、语句)
    上节的基础内容知识,这节我们会用到。默认已读。

前端培训-初级阶段(13) - ECMAScript (内置对象、函数)

我们要讲什么

  1. ECMAScript 基础对象(Object、Boolean、Number、String)
  2. 常用内置对象(Date、Array、Math、RegExp、global、Function、Event、arguments、JSON)
  3. ECMAScript 函数(声明、调用、返回值、闭包、递归)

ECMAScript 基础对象

在 ECMAScript 中,所有对象并非同等创建的。
一般来说,可以创建并使用的对象有三种:本地对象、内置对象和宿主对象。

ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。它们包括:Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
ECMA-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用法作用
属性lengthObject.lengthObject.length 值为1
属性prototypeObject.prototype可以为所有 Object 类型的对象添加属性
方法assignObject.assign()通过复制一个或多个对象来创建一个新的对象
方法createObject.create()使用指定的原型对象和属性创建一个新对象
方法definePropertyObject.defineProperty()给对象添加一个属性并指定该属性的配置
方法definePropertiesObject.defineProperties()给对象添加多个属性并分别指定它们的配置
方法entriesObject.entries()返回给定对象自身可枚举属性的[key, value]数组
方法freezeObject.freeze()冻结对象:其他代码不能删除或更改任何属性
方法getOwnPropertyDescriptorObject.getOwnPropertyDescriptor()返回对象指定的属性配置
方法getOwnPropertyNamesObject.getOwnPropertyNames()返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名
方法getOwnPropertySymbolsObject.getOwnPropertySymbols()返回一个数组,它包含了指定对象自身所有的符号属性
方法getPrototypeOfObject.getPrototypeOf()返回指定对象的原型对象
方法isObject.is()比较两个值是否相同。所有 NaN 值都相等(这与==和===不同)
方法isExtensibleObject.isExtensible()判断对象是否可扩展
方法isFrozenObject.isFrozen()判断对象是否已经冻结
方法isSealedObject.isSealed()判断对象是否已经密封
方法keysObject.keys()返回一个包含所有给定对象自身可枚举属性名称的数组
方法preventExtensionsObject.preventExtensions()防止对象的任何扩展
方法sealObject.seal()防止其他代码删除对象的属性
方法setPrototypeOfObject.setPrototypeOf()设置对象的原型(即内部[[Prototype]]属性)
方法valuesObject.values()返回给定对象自身可枚举值的数组
原型属性([]).constructor === ArrayObject.prototype.constructor特定的函数,用于创建一个对象的原型
原型属性([]).__proto__ === Array.prototypeObject.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用法作用
属性EPSILONNumber.EPSILON两个可表示(representable)数之间的最小间隔
属性MAX_SAFE_INTEGERNumber.MAX_SAFE_INTEGERJavaScript 中最大的安全整数 (253 - 1)
属性MAX_VALUENumber.MAX_VALUE能表示的最大正数。最小的负数是 -MAX_VALUE
属性MIN_SAFE_INTEGERNumber.MIN_SAFE_INTEGERJavaScript 中最小的安全整数 (-(253 - 1))
属性MIN_VALUENumber.MIN_VALUE能表示的最小正数即最接近 0 的正数 (实际上不会变成 0)。最大的负数是 -MIN_VALUE
属性NaNNumber.NaN特殊的“非数字”值
属性NEGATIVE_INFINITYNumber.NEGATIVE_INFINITY特殊的负无穷大值,在溢出时返回该值
属性POSITIVE_INFINITYNumber.POSITIVE_INFINITY特殊的正无穷大值,在溢出时返回改值
属性prototypeNumber.prototypeNumber 对象上允许的额外属性
方法isNaNNumber.isNaN()确定传递的值是否是 NaN
方法isFiniteNumber.isFinite()确定传递的值类型及本身是否是有限数
方法isIntegerNumber.isInteger()确定传递的值类型是“number”,且是整数
方法isSafeIntegerNumber.isSafeInteger()确定传递的值是否为安全整数 ( -(253 - 1) 至 253 - 1之间)
方法toIntegerNumber.toInteger()计算传递的值并将其转换为整数 (或无穷大)
方法parseFloatNumber.parseFloat()和全局对象 parseFloat() 一样
方法parseIntNumber.parseInt()和全局对象 parseInt() 一样
原型方法toExponentialNumber.prototype.toExponential()返回以科学计数法表示的数字字符串
原型方法toFixedNumber.prototype.toFixed()返回固定小数位的数字字符串(四拾伍入)
原型方法toLocaleStringNumber.prototype.toLocaleString()返回以本地语言为主的数字字符串。会覆盖 Object.prototype.toLocaleString()。
原型方法toPrecisionNumber.prototype.toPrecision()返回固定位数表示的数字字符串(小数点不记位,四拾伍入、位数不够会返回科学计数法)
原型方法toStringNumber.prototype.toString()返回以指定基数表示的数字字符串。会覆盖 Object.prototype.toString()
原型方法valueOfNumber.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)起经过的毫秒数。

  1. 实例化方式

    new Date();//当前时间
    new Date(Number);//传入的毫秒数转换成时间
    new Date(dateString);//传入的时间格式转换为时间。这里有一些坑(低版本IE、ios、chrome)实现的规范不一样,导致有的格式解析不出来,可以用[momentjs][3]。
    new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
    注意:只能将 Date 作为构造函数调用,才能实例化(instantiate) Date 对象:若将它作为常规函数调用(即不加 new 操作符),则将会返回一个字符串,而非 Date 对象。另外,不像其他的 JavaScript 对象类型,Date 对象没有字面量语法(literal syntax)。
  2. 方法

    1. Date.now() 返回自 1970-1-1 00:00:00 UTC(世界标准时间)至今所经过的毫秒数。
      等效写法+new Date(),new Date().getTime()
    2. Date.parse() 解析一个表示日期的字符串,并返回从 1970-1-1 00:00:00 所经过的毫秒数。
    3. Date.UTC() 接受和构造函数最长形式的参数相同的参数(从2到7),并返回从 1970-01-01 00:00:00 UTC 开始所经过的毫秒数。
  3. 原型方法

    1. getDay()周,getFullYear()年,getMonth()月,getDate()日,getHours()时,getMinutes()分,getSeconds()
    2. getTimezoneOffset() 返回当前时区的时区偏移。
    3. set方法同上,需要注意的地方有setHours()可以把时分秒毫秒都设置了

Array

  1. Array数组对象的forEach、map、filter、reduce
  2. join 合并成串
  3. concat 合并其他数组
  4. slice 分割数组

Math

  1. Math.random() 随机数。来个公式(end-start+1)*num+start
    比如 60-90区间内(90-60+1)*Math.random()+60>>0即可得到区间内整数
  2. Math.ceil 向上取整Math.ceil(5.1)
  3. Math.floor 向下取整Math.floor(1.9)
  4. Math.round 四拾伍入Math.round(2.3)
  5. Math.pow Math.pow(3,5)等同于3**5,但是前者兼容更好

RegExp

原生的方法其实很少用。需要注意的地方是,有部分函数会记录上次差到的点。一般都是用字符串的 replacematch

JSON

低版本 IE 没有。需要使用 eval
提供了 JSON.stringifyJSON.parse()用来序列化与反序列化

//提供一个tips,你可以在控制台试试哟。
JSON.stringify([{
    userid: 7848950,
    nickname: 'abc'
},{
    userid: 920110633,
    nickname: 'abc'
},{
    userid: 7848952,
    nickname: 'abc'
}], null, '   ')

ECMAScript 函数(声明、调用、返回值、闭包、递归)

函数声明

  1. 函数声明 function fun(){}
  2. 函数表达式 fun = function fun(){}
  3. IFFE void function(){console.log(1)}()
  4. 构造函数 new Function('a','b','return a+b')(1,2)

函数调用

function fun(){console.log(1)};fun() 通过括号来调用

返回值

function fun(){return 1};console.log(fun()) 函数内部通过return来返回

闭包

  1. 什么是作用域
    作用域(scope)指的是变量存在的范围。 在 es5 中的,Javascript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。(es6中又新增了块级作用域)全局作用域可以在代码的任何地方都能被访问。
  2. 什么是作用域链
    是指作用域生成的路径。当代码在一个执行环境中执行时,就会创建一个作用域链。我们有可能两个 function 内都使用了 state 这个变量,我们不希望他共享,他被限制在了自己的作用域中。
    内部环境可以通过作用域链访问所有外部环境,但是外部环境不能访问内部环境中的任何变量和函数。
    在 js 中与作用域链相似的有原型链
  3. 那么什么是闭包呢?
    闭包就是依赖这个特性,思考如下代码。可以让我们的代码和外部环境隔离。

    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);
   }
}

后记

主讲人的讲稿地址
这里也要吐槽一下自己,断更这么久,实在是太忙了。

参考文献

  1. JavaScript 标准库