zoukankan      html  css  js  c++  java
  • Part1.3 ECMAScript和JavaScript及TypeScript

    文章内容输出来源:拉勾教育大前端训练营

    ECMAScript

    - 浏览器中的javascript指的是ES + Web提供的Api(dom bom)
    - node环境中javascript指的是ES + node提供的Api
    

    作用域

    全局作用域(公共作用域)

    1. 在全局作用域中的函数,变量都是公用的.所有相同的变量名称重复命名都会冲突导致报错
    2. 函数内部直接赋值变量会把变量提升为全局变量
    
    var a = 3
    function a() {
        a = 2;
        console.log('func a')   
    }
    console.log(a())//TypeError: a is not a function
    
    var a = 3
    function test() {
        a = 2;
        console.log(a)   
    }
    console.log(test())//2
    
    
    function test() {
        console.log(a) //未声明 报错
        a = 2;
        console.log(a)   
    }
    console.log(test()) //a is not defined
    console.log(a)
    
    
    
    function test() {
        a = 2;
        console.log(a)   //2
    }
    
    console.log(test())
    console.log(a)  //2
    

    函数作用域

    1. 函数内部使用var声明变量(局部变量)只能在函数作用域内使用,外部无法访问到
    
    function test() {
       
       var a = 2;
        console.log(a) //2
    }
    
    console.log(test()) 
    console.log(a)//a is not defined
    

    块级作用域(ES2015新增)

    1. {} 花括号包括的就是块级作用域
    2. let 关键字可以绑定到所在的作用域中
    3. var 关键字声明的变量会提升到最近的函数作用域当中(函数作用域)
    
    var  a=1;
    function test() {
        function test1() {
            if (true) {
               var a = 44;
                console.log(a) //44
            }
            console.log(a) //44
        }
        test1()
        console.log(a) //1
    }
    
    
    console.log(a) //1
    console.log(test())
    console.log(a) //1
    
    

    const 常量

    • 必须有初始值,变量声明过后无法修改,只能修改其中的值 (无法修改的是内存地址,但是存储在内存空间中的数据是可以修改的)
    const a = { a: 1 };
    a.a= 2
    console.log(a) //{ a: 2 }
    
    const b=2;
    b=3 //TypeError: Assignment to constant variable.
    

    解构

    数组解构
    const arr=[1,2,3,4]
    const [first,secend,...rest]=arr;
    console.log(first)//1
    console.log(rest)//[3,4]
    
    对象解构
    const obj ={
        name:'aa',
        age:18
    }
    
    const {name,age}=obj
    
    console.log(name)//aa
    
    console.log(age)//18
    

    模板字符串

    • 使用 ` ` 声明字符串模板,'${}'插入值
    const obj ={
        name:'aa',
        age:18,
        ['姓名']:'哈哈'
    }
    
    console.log(`字符串输出${obj.姓名}`)//字符串输出哈哈
    

    箭头函数

    • 好处:简化代码 , 不会改变this 的指向
    • 多个参数用(),多行的函数体使用{} 多行需要自己手动return 返回值
    const obj ={
        name:'aa',
        age:18
    }
    
    
    let age1=obj=>{
        return this
    }
    console.log(age1(obj))//{}
    

    对象字面量

    计算属性名
    • [ str ] str表达式的计算结果会作为这个对象属性的属性名
    const obj ={
        name:'aa',
        age:18,
        ['姓名']:'哈哈'
    }
    
    
    let age1=obj=>{ 
        return obj.姓名
    }
    console.log(age1(obj)) //哈哈
    

    Object.assign 对象拷贝

    • 可以将多个对象的原属性复制到目标对象中,如果相同会覆盖目标对象的属性(值传递,不存在引用关系.属于深拷贝)
    • Object.assign(targer,...objs) 后面多个obj覆盖到targer目标中
    const obj={
        name:'test'
    }
    console.log(Object.assign({},obj)) //{ name: 'test' }
    console.log(Object.assign({},obj,obj1)) //{ name: 'test', age: '18' }
    

    Object.is 同值比较

    • 同值比较 (区分正负,NaN) === 无法区分的可以用Object.is()
    console.log(Object.is(-0,+0)) //false
    console.log(Object.is(NaN,NaN)) //true
    console.log(-0===+0)//true
    console.log(NaN===NaN)//false
    

    Proxy 对象代理器

    const obj = {
        name: 'test'
    }
    
    const newProxy = new Proxy(obj, {
        get(targer, property) {
            return property in targer ? targer[property] : 'default'
        },
        set(targer, property, value) {
            if (property === "age")
                if (!Number.isInteger(value))
                    throw new TypeError("错误的数据类型")
            targer[property] = value
            console.log(targer)
        }
    })
    console.log(newProxy.name) //test
    console.log(newProxy.xx) //default
    newProxy.age = "哈哈" //TypeError: 错误的数据类型
    console.log(newProxy.age)
    

    Proxy对比object.defineProperty

    • object.defineProperty 只能监测到属性的读写
    • Proxy 可以监测到更多
    • object.defineProperty 监视属性的变化,需要额外的写很多的属性监视逻辑
    const obj = {
        name: 'test'
    }
    
    const newProxy = new Proxy(obj, {
        get(targer, property) {
            return property in targer ? targer[property] : 'default'
        },
        set(targer, property, value) {
            if (property === "age")
                if (!Number.isInteger(value))
                    throw new TypeError("错误的数据类型")
            targer[property] = value
            // console.log(targer)
        },
        delete(targer,property){
           delete targer[property]
        }
    })
    // console.log(newProxy.name)
    // console.log(newProxy.xx)
    newProxy.age = 18
    delete  newProxy.age
    console.log(newProxy.age) // default
    

    Proxy 对数组的操作监视

    • 以非侵入的方式监管了对象的读写
    const list = [];
    let arrProxy = new Proxy(list, {
        set(targer, property, value) {
            targer[property] = value
            return true  //返回写入成功,不写返回值会报错('set' on proxy: trap returned falsish for property '0')
        }
    })
    
    arrProxy.push(200)
    arrProxy.push({ name: 'test' })
    console.log(list)
    

    Reflect 一套用于对象操作类(api),13个方法

    • Proxy 默认是调用Reflect方法
    • 使用带来的好处:统一了操作对象的api
    const obj = {
        name: 'test'
    }
    // console.log('name' in obj) //true
    // console.log(delete obj['name']) //true
    // console.log(Object.keys(obj))//[]
    console.log(Reflect.has(obj,'name'))//true
    console.log(Reflect.deleteProperty(obj,'name'))//true
    console.log(Reflect.ownKeys(obj))//[]
    

    class 类

    • 以前的声明类型是用function,使用原型链增加原型方法
    • ES6中可以使用class关键字来声明一个类型
    • 使用extends关键字继承父类
    • 使用super关键字指向继承的父类,访问父类,只能在构造函数中使用,否则会报错(SyntaxError: 'super' keyword unexpected here)
    • static 关键字 声明静态方法,无法在内部使用this,指向到当前的类型
    function myCls() {
        this.name = "测试"
    }
    
    myCls.prototype.say = function () {
        return this.name
    }
    
    let my = new myCls()
    console.log(my.say())//测试
    class myCls2  extends myCls{
        //静态方法
        static create(no,name) {   
            return new myCls2(no,name)
        }
        constructor(no,name) {
            super(name)
            this._no = no
        }
        //实例方法
        say() {
            return this._no
        }
    }
    
    // let my2 = new myCls2('测试2')
    // console.log(my2.say())//测试2
    let my2=myCls2.create(1,'测试2')
    console.log(my2.say())
    

    set 数据解构

    • 不允许重复的集合对象
    • .size() 获取个数
    • .has() 判断存在
    • .delete() 删除指定元素
    • .clear() 清空
    • array.from() ... 展开 [ ... ] 得到对象数组

    Map 键值对集合

    • 对象中的键是string类型的,而Map可以任意类型的值作为键
    let m=new Map()
    m.set({name:123},90)
    console.log(m)
    
    let om=new Object()
    om.s=99;
    console.log(om)
    

    Symbol

    • 以往变量的名称会重复,通过口头协议或者xx_变量名
    • 用Symbol的目的是为了定义一种独一无二的属性,用于对象的私有属性
    • 用Symbol 函数创建的值一定是唯一的值
    • 可以用全局变量和Symbol.for(str) (维护的是str 字符串和Symbol的关系,都是string类型.都会被转换成string类型)
    • 使用 for In 循环,object.keys(),JSON.Stringify()都无法拿到用[Symbol()]声明的变量名称
    • Object.getOwnPropertySymbols() 拿取的是Symbol类型的属性名称

    for of 遍历

    • 数据的统一遍历方式 break 终止遍历
    • foreach 无法终止遍历
    • arr.some() 返回true终止遍历
    • arr.every() 返回false 终止遍历

    类型安全

    强类型和弱类型
    • 强类型
      • 编译时就会报错 ,错误更早的暴露
      • 代码更智能,编码更准确(成员变量 类型不明确 导致编辑器提示不出来,只能自己手写)
      • 重构更牢靠 (修改成员变量名称后 无法找到引用的地方,没有编译环节,导致程序无法执行)
      • 减少不必要的类型判断
    • 弱类型
      • 运行时报错
      • 各种类型判断,增加代码复杂度
    类型系统
    • 动态类型语言 变量没有类型 变量的值有类型的区分

    类型限制

    • 原始类型 string number bool null undefined object Symbol 7种

    Flow

    • 2014年facabook 推出的工具 用于编码阶段的类型判断,通过类型注解达到类型判断.
    • npm i flow-bin 安装
    • npm flow init 初始化
    • 文件头上需要加上 //@flow
    • flow stop 停止命令
    • npm flow-remove-types
    • npm flow-remove-types .src -d dist 参数一(src) 源代码所在的目录地址 参数二(-d dist) 转换的输出
    function (nb :number){
        return nb;
    }
    
    //数组类型
    let arr:Array<number>=[1,2,3] //<> 指定成员类型
    let arr:number[]=[1,3,4] //:number[] 效果一样
    let arr:[string,number]  //元组数据类型(固定长度数组)
    
    
    //对象类型
    let obj:{foo?:string,bar:number}
    let obj:{[string]:string}  //限制对象属性 key 必须是字符串 ,值也必须是字符串
    
    //函数类型
    let fn:(string,number)=>void =function('aa',1){} //指定2个参数类型分别是string 和number,指定无返回值(undefind)
    
    //type 关键字设置类型  
    type str=string
    
    //字面量类型
     type s=string | number //string或者number类型
     
    //maybe 设置可为空
     const b: ?number = undefind  
     const b: number | null | void = undefind
     
    
    
    mixed & any 类型
    • any 弱类型 编译可以过 但运行未知
    • mixed 强类型 不做类型判断编译报错

    TypeScript

    • TypeScript 是 JavaScript 的超集,扩展了 JavaScript 的语法

    • string number bool 类型在ts中可以为空(null)值的

    • 优点:

      • typescript是渐进式的,便于学习
      • 注解、类型推断增加了代码的可读性.在编译阶段可以即使发现错误,而不是等到上线阶段
    • 缺点:

      • 语言增加了很多概念,增加了学习成本
      • 要多些一些类型的定义,class对象,对于短期项目增加了成本
    • 安装及使用

      • npm i typescript -d
      • tsc --locale zh-CN 使用中文错误消息(开发不推荐)
      • tsc xxx.ts 编译ts文件
      • tsc --init 新增配置文件 //成功:message TS6071: Successfully created a tsconfig.json file.
      • tsc 根据配置文件运行整个工程文件的ts文件编译
    • 断言 数据类型选择 (编译时的类型选择)

      let num = 123 as number 
      let numb = '123' as number //直接报错
      /**类型 "string" 到类型 "number" 的转换可能是错误的,因为两种类型不能充分重叠。
      如果这是有意的,请先将表达式转换为 "unknown"。
      **/
    
    • 接口 类型约束 运行时不存在
    //设置动态接口
    interface CacheTs {
        readonly name: string //只读
        [prop: string]: any   //属性名string 值可以为任何值
    };
    
    let cc: CacheTs = {
        name: '张三',
        processName: '测试'
    };
    //cc.name='里斯' //报错无法分配到 "name" ,因为它是只读属性。
    console.log(cc.name);//张三
    
    • 枚举
    enum book {
        '天文',
        '地理',
        '文学',
        '言情',
        '科幻'
    }
    console.log(book[0]) //天文
    
      • abstract 抽象类 (跟接口相同)
        • 不能被实例化
        • 继承抽象类的类必须实现抽象类的所有方法
      • 访问修饰符
        • public 公用
        • private 私有
        • protected 继承了就等于public没有继承就是private
      • 属性修饰符
        • readonly 只读
    • 接口
      • 只定义,不做具体的实现

        • implements 实现接口
          • 类实现接口需要实现所有具体的方法
          • 不能被实例化
        • extends 继承
          • 对象继承类,子类的构造函数必须执行一次 super() 函数
    interface people {
        name: string | null | undefined
        age: number | undefined
    }
    class man implements people {
        name: string | null | undefined = undefined
        age: number | undefined = undefined
        sex: number | null | undefined = undefined
        constructor(name: string, sex: number, age: number) {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
    }
    let p = new man("张三", 1, 18)
    console.log(p) //man { name: '张三', age: 18, sex: 1 }
    

    javascript 的性能优化

    ...未完待续

  • 相关阅读:
    最小最大数
    ubuntu14.04在虚拟环境中安装flask遇到的问题
    线性时间排序
    NSURLSession详细介绍,以及一些坑位的介绍
    IOS笔记 本地化多语言支持
    Documenting in Xcode with HeaderDoc Tutorial
    高效使用你的Xcode
    Xcode 7遇到 App Transport Security has blocked a cleartext HTTP 错误
    iOS bug解决方案(02)
    CGRect 的使用
  • 原文地址:https://www.cnblogs.com/zhuzy/p/13405895.html
Copyright © 2011-2022 走看看