day15-ECMAScript和ES5新增

JavaScript构成

  • BOM 操作浏览器对象
  • DOM 操作文档对象
  • ECMAScript 基础语法

ECMAScript介绍

  • ECMAScript 是对应 js 的基础语法,里面包含 js 中除 dom 操作和 bom 的所有内容。ECMAScript主要拆分为俩个单词 ECMA (欧洲计算机协会) 、Script (脚本)。
  • ECMAScript 简称(es)他主要的版本有 ES3、ES5、ES6...对应的版本管理以及切换是由不同兼容问题产生的。
  • 低版本的兼容就比较好,高版本的兼容性较差。在项目中我们可以使用 bable.js 来进行生成代码的版本切换(后续框架中必然使用的)。ES3为基础版本他支持市面常用的所有浏览器,ES5支持市面上大多数浏览器, ES6只支持高版本浏览器。

ECMAScript的版本

  • ES3 基础版本(大多数的基础内容都属于es3)
  • ES5 (ES2009) 他在es3上增强对应的规范性以对应的方法
  • ES6 (ES2015) 他在es5的基础上扩展了对应的类及对应的处理

ES5新增内容

怪异模式

平常书写代码没有多大的规范性、比较随意,平常的这种模式就被称为怪异模式。

严格模式

严格模式是采用具有限制性 JavaScript 变体的一种方式,具备规范性。

严格模式的书写

  • 使用 use strict 来声明且必须书写在首行
<script>
    'use strict'
    hello = '你好'
    console.log(hello) //报错,因为在严格模式下,必须要声明
</script>

 严格模式的特性

  • 声明变量必须使用var关键词声明
  • 函数中的 this 不允许指向全局对象(global)(window)
  • arguments 中的实参不同步:严格模式下,函数的 arguments 对象会保存函数被调用时的原始参数。arguments[i] 的值不会随与之相应的参数的值的改变而变化,同名参数的值也不会随与之相应的 arguments[i] 的值的改变而变化。
  • 函数名的参数唯一
  • 严格模式要求一个对象内的所有属性名在对象内必须唯一
  • 函数声明只处于上下文对象中
  • 禁止使用八进制方法
  • 将一切不规范的地方全部抛出错误

【示例】:函数声明只处于上下文对象中

"use strict";
if (true) {
  function f() { } // !!! 语法错误
  f();
}

for (var i = 0; i < 5; i++) {
  function f2() { } // !!! 语法错误
  f2();
}

function baz() { // 合法
  function eit() { } // 同样合法
}

数组新增的高阶函数

高阶函数就是以函数作为参数的函数被称为高阶函数

  • forEach 遍历 (返回值为void):没有返回值
var arr = ['a','b','c','d']
//传入的函数为操作函数
//传入的函数有三个参数 分别为遍历的值 遍历的下标 遍历的数组
arr.forEach(function(value,index,array){
    console.log(value,index,array)
//输出值为
//  a 0 ['a', 'b', 'c', 'd']
//  b 1 ['a', 'b', 'c', 'd']
//  c 2 ['a', 'b', 'c', 'd']
//  d 3 ['a', 'b', 'c', 'd']
})
  • map 遍历 (返回值是数组 且返回的数组个数和遍历的数组个数一致)
var arr = ['1', '2', '3', '4']
var nums = arr.map(function(v,i,arr){
// 遍历数组,找出下标为偶数的下标并输出
    if(i%2 == 0){
        return i
    }
})
console.log(nums)//[0,undefined,2,undefined]

forEach 和 map 的相同点和区别

【相同点】

  • 都是循环遍历数组中的每一项。
  • forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:(遍历的值value,遍历的下标index,遍历的数组 arr)
  • 匿名函数中的 this 都是指向 Window。
  • 只能遍历数组

【区别】

  • 区别在于forEach() 没有返回值,map() 有返回值
  • forEach() 会改变原数组,map() 不会改变原数组
  • filter 过滤 (返回的是一个数组)
//filter用于过滤 
//里面传入的对应的函数一定返回值boolean 
//true就是添加的返回的数组 如果是false就不添加
//v表示对应的值 i表示下标 arr表示数组
var filterArr = ['a', 'b', 'c', 'ab'].filter(function (v, i, arr) {
    return /a/.test(v) // 过滤含a的字符并返回成一个数组
})
console.log(filterArr)  // ['a', 'ab']
  • every 每个都满足条件返回 true (传入的函数的必须返回boolean)
//every 当前是否每个都满足条件
var is = ['1', '2', '3', '4'].every(function (v, i, arr) {
    return v > 3
})
console.log(is) //false
  • some 只有有一个满足条件返回false (传入的函数的必须返回的boolean)
//some当前是否存在满足条件的
var is = ['1', '2', '3', '4'].some(function (v, i, arr) {
    return v > 3
})
console.log(is)//true
  • reduce:从左到右,用于计算

语法:reduce(function(prev,current,i,arr){},初始值)

第一个参数为处理函数 ,第二个参数为初始值 (如果没有设置默认为第一个 如果设置那么就对应设置的值)

  • prev :前面的结果值 (默认为数组的第一个值), 如果第二个参数设置了初始值那么 prev 值为初始值
  • current :当前值 (默认从第二个开始) 设置了第二个参数那么默认从第一个开始
  • i :默认从下标为1开始 设置了第二个参数那么下标从0开始

【示例】 求数组内元素的和

var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
})
console.log(arr, sum);

打印结果:
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10

var  arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);
    return prev + cur;
},0) //注意这里设置了初始值
console.log(arr, sum);

打印结果:
0 1 0
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10

  • reduceRight :从右到左开始计算
var numbers = [2, 45, 30, 100];
function getSum(total, num,i,arr) {
   console.log(total, num, i);
  return total - num;
} 
console.log( numbers.reduceRight( getSum ) )//23

打印结果:

100 30 2

70 45 1

25 2 0

23

高阶函数的手动封装实现

  • forEach
var arr = [1,2,3,4]
//封装myForEach
function myForEach(callback) {
    if (typeof callback != 'function') {
        throw new Error('参数错误')
    }
//遍历执行处理函数
    for (var i = 0; i < arr.length; i++) {
        callback(arr[i], i, arr)
    }
}
//调用
myForEach(function (v, i, arr) {
    console.log(v, i, arr)
})

打印结果:

1 0  [1, 2, 3, 4]
2 1  [1, 2, 3, 4]
3 2  [1, 2, 3, 4]
4 3  [1, 2, 3, 4]

  • map:不会改变原数组,返回一个新的数组
var arr = [1, 2, 3, 4]
//封装myMap
function myMap(callback) {
    if (typeof callback != 'function') {
        throw new Error('参数错误')
    }
    //返回的内容
    var results = []
    //遍历执行处理函数
    for (var i = 0; i < arr.length; i++) {
        results.push(callback(arr[i], i, arr))
    }
    return results
}
myMap(function(v, i, arr) {
    console.log(v + 'hello', i, arr);
    console.log(myMap(function(v) {
        return v + 'hello'
    }))
})

打印结果:

1hello 0 [1, 2, 3, 4]
2hello 1 [1, 2, 3, 4]
3hello 2 [1, 2, 3, 4]
4hello 3 [1, 2, 3, 4]

['1hello', '2hello', '3hello', '4hello']

  • every
var arr = [1, 2, 3, 4]
//封装myEvery
function myEvery(callback) {
    if (typeof callback != 'function') {
    throw new Error('参数错误')
    }
    //遍历执行处理函数
    for (var i = 0; i < arr.length; i++) {
    //只要有一个false,那么直接返回false
        if (!callback(arr[i], i, arr)) {
            return false
        }
    }
    return true
}
console.log(myEvery(function(v){return v<10}))

打印结果:

true

  • some
var arr = [1, 2, 3, 4]
//封装mySome
function mySome(callback) {
    if (typeof callback != 'function') {
        throw new Error('参数错误')
    }
    //遍历执行处理函数
    for (var i = 0; i < arr.length; i++) {
    //只要有一个true,那么直接返回true
        if (callback(arr[i], i, arr)) {
            return true
        }
    }
    return false
}
console.log(mySome(function (v) {
    return v >= 4
}))

打印结果:

true

  • filter:不会改变原数组
var arr = [1, 2, 3, 4]
//封装myFilter
function myFilter(callback) {
    if (typeof callback != 'function') {
        throw new Error('参数错误')
    }
    //准备一个返回的数组
    var results = []
    //遍历执行处理函数
    for (var i = 0; i < arr.length; i++) {
    //当里面返回的true填入到数组
        if (callback(arr[i], i, arr)) {
            results.push(arr[i])
        }
    }
    return results
}
console.log(myFilter(function(v){return v>2}))

打印结果:

[3, 4]

  • reduce *
var arr = [1, 2, 3, 4]
//myReduce
function myReduce(callback, value) {
    if (typeof callback != 'function') {
        throw new Error('参数错误')
    }
    //value被传递的情况
    var index = 0
    var previous = value
    //如果value值没有被传递 那么我的遍历从下标1开始 初始值为对应的下标为0的元素
    if (typeof value == 'undefined') {
    //判断是否为空数组
        if(arr.length == 0){
            throw new Error('Reduce of empty array with no initial value')
        }
        index = 1
        previous = arr[0]
    }
    //遍历计算值
    for(; index < arr.length ; index++){
    //调用传入的函数 得到对应的结果值 再覆盖对应的结果
        previous = callback(previous,arr[index],index,arr)
    }
    //返回结果
    return previous
}
console.log(myReduce (function (prev,current , index , arr){
    console.log( previous , current , index , arr);
    return prev+current
},20))

打印结果:

20 1 0 [1, 2, 3, 4]
21 2 1 [1, 2, 3, 4]
23 3 2 [1, 2, 3, 4]
26 4 3 [1, 2, 3, 4]
30

  • reduceRight
      var arr = [1, 5, 3, 2, 9]       
      // reduceRight
      function myReduceRight(callback, value) {
            var index = arr.length - 1
            var prev = value //前面的值
            if (typeof callback != 'function') {
                throw new Error('参数错误')
            }
            if (typeof value == 'undefined') {
                if (arr.length == 0) {
                    throw new Error('Reduce of empty array with no initial value')
                }
                index = arr.length - 1
                var current = arr[arr.length]
                prev = 0
            }
            for (var i = index; i >= 0; i--) {
                prev = callback(prev, arr[i], i, arr)
            }
            return prev
        }
        console.log(myReduceRight(function(prev, current, i, arr) {
            console.log(prev, current, i, arr)
            return prev + current
        }, 2));

打印结果:

2 9 4 [1, 5, 3, 2, 9]
11 2 3 [1, 5, 3, 2, 9]
13 3 2 [1, 5, 3, 2, 9]
16 5 1 [1, 5, 3, 2, 9]
21 1 0 [1, 5, 3, 2, 9]
22

  • filter
       var arr = [1, 5, 3, 2, 9]      
       function myFilter(callback) {
            if (typeof callback != 'function') {
                throw new Error('参数错误')
            }
            var result = []
            for (var i = 0; i < arr.length; i++) {
                if (callback(arr[i], i, arr)) {
                    result.push(arr[i])
                }
            }
            return result
        }
        console.log(myFilter(function(v) {
            return v > 2
        }));

打印结果:

[5, 3, 9]

this指向的改变(Function对象的方法)

  • bind (返回一个函数 需要手动调用),传参跟对应执行函数传的参是一样的
  • apply(自动调用 返回值是对应的函数执行的结果),传参必须是数组
  • call (自动调用 返回值也是对应的函数执行的结果),传参必须是一个个的元素

【注意】:

  • 传参个数要相同,少传参会返回 NaN,多传参不会调用多传的参数
  • bind 函数执行完返回的函数不能被 apply 和 call 进行二次更改 this 指向

       var obj = {
            sayHi: function() {
                console.log(this); //返回obj对象
            }
        }
        obj.sayHi()

        function sayHello() {
            console.log(this); //返回的是window
        }
        sayHello()

        // bind、call、apply用来改变this的指向
        var fn = obj.sayHi.bind(window)
        fn() //打印得是window
        console.log(fn); //返回一个新的函数
        console.log(fn == obj.sayHi); //false

        console.log(sayHello.apply(obj)); //更改this指向obj
        console.log(sayHello.call(document)); //更改this指向document

        //------------------------------------------
        function sum(num1, num2) {
            return num1 + num2
        }
        // 传递参数跟对应的函数执行传参是一样的
        console.log(sum.bind(String)(2, 3));
        // 传递参数是对应的数组
        console.log(sum.apply(document, [2, 3]));
        // 传递参数时一个个的元素
        console.log(sum.call(document.body, 2, 1));

getter setter (对象里面)

  • get 用于获取,必须是访问属性名
  • set 用于设置,必须是访问属性名
var obj = {
    _name:'hello',
    get name() {
        console.log('getter 调用了')
// return this.name + '张三' 出错无限递归
        return this._name +'张三'
    },
    set name(value) {
        this._name = value
        console.log('setter 调用了')
    }
}
console.log(obj.name) //调用getter
obj.name = 'hi'//调用setter
console.log(obj.name) //调用getter

打印结果:

getter 调用了
hello张三
setter 调用了
getter 调用了
hi张三

【 补充新增】

  • 字符串的 trim 方法 (去前后空格)
  • 数组的静态方法 Array.isArray:返回 Boolean 值
  • 数组的 indexOf 及 lastIndexOf
  • JSON 的序列化方法及反序列化方法:JSON.stringify(),JSON.parse()
  • Object 的相关方法:object.defineProperty 等
//静态方法就是首字母大写的类型(class类)名来调用的方法 (static修饰的)
console.log(Array.isArray([])) //true 判断是否为数组

console.log(['a','b','c'].indexOf('a'))//0 获取对应的第一个出现的下标
console.log(['a','b','c','a'].lastIndexOf('a'))//3 从后往前获取对应的第一个出现的
下标
console.log(['a','b','c'].indexOf('a',1))//-1 第二个指定是对应的开始下标找不到返
回-1
console.log(['a','b','c'].lastIndexOf('a',1))//0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值