zoukankan      html  css  js  c++  java
  • Javascript中的基本数据类型,如何判断数据类型,作用域链的理解

    第一部分:Javascript中的数据类型

    javascript中 基本数据类型有 五种, 数字 number 字符串 string  布尔 boolean  未定义 undefined 空值 null

    另外有引用数据类型三种: 对象 object   数组 array  函数 function

    在ES6中,新增了三种数据类型  Set Map 和 Symbol

    第二部分:如何判断一个数据的数据类型呢?

    方法一:使用typeof 方法

    示例表明,使用typeof 方法可以判断出 number, string, boolean, undefined, object, symbol, function这7种结果,二话不说 上代码

    typeof 1  // number
    
    typeof 'a' //  string
    
    typeof false // boolean
    
    typeof undefined  // undefined
    
    typeof [] // object
    
    typeof {} // object
    
    typeof null // object
    
    const a = function(){}
    
    typeof a // function 
    
    typeof new Set()  // object
    
    typeof new Map() // object
    
    typeof Symbol // function
    
    typeof Symbol() // symbol

    方法二: 利用instanceof 用来判断构造函数,注意 只有引用类型的数据才可以使用 instanceof 方法,

    基本类型中的 数字 字符串 布尔值 可以利用 new 方法生成对象 

    比如 new Number(1) 就是一个对象了,就可以使用instanceof 方法 

    new Number(1) instanceof Number // true
    
    new String('str') instanceof String  // true 
    
    new Boolean(false) instanceof Boolean // true
    
    [] instanceof Array // true
    
    {} instanceof Object // true
    
    console.log instanceof Function // true
    
    console.log instanceof Function // true

    new Map() instanceof Map // true

    new Set() instanceof Set() // true

    那么以此就可以编写一个判断数据类型的方法啦

    function getType(param) {
        if( arguments.length === 0 ) {
             return '请传入参数'
        }
    
        if(param === null) {
             return 'null'
       }
    
        const type = typeof param 
        
        if( type !== 'object') { // 基本类型数据或symbol或function
              return type
        } else { // 引用类型
           if(param instanceof  Array){
              return 'array'
           } else if(param instanceof Set ) {
               return 'set'
           } else if(param instanceof Map) {
               return 'map'
           } else if(param instanceof Object) {
    return 'object'
    } } }

    附上测试结果:

    getType(1) // number
    
    getType('a') // string
    
    getType(false) // boolean
    
    getType([]) // array
    
    getType(null) // null
    
    getType(undefined) // undefined
    
    getType({}) // object
    
    getType(new Set()) // set
    
    getType(new Map())  // map
    
    getType(Symbol())  // symbol
    
    getType(Symbol) // function
    
    getType(console.log)  // function

    3.下面来讲讲 数据类型及其对应的构造函数

    在Javascript的数据类型中,除了 null ,undefined其他都有自己的构造函数

    比如 数字的构造函数 Number, 字符串构造函数 String, 布尔 Boolean   , 对象 Object, 函数 Function , Set()    Set, Map()  Map

    在基本类型中  可以使用 Number(1)  === 1 , String('a') === 'a',  Boolean(false) === false 

    而 new Number(1) 会得到一个对象,这个对象只有一个属性__proto__ 这个属性指向构造函数 Number 

    const num = new Number(1) 
    
    typeof num // 'object'
    
    typeof Number(1) //  number
    
    num.__proto__ === Number.prototype
    
    // Number.ptototype 下有多个方法 valueOf, toString,toFixed等,实际上对数字调用这些方法其实是调用Number.prototype上的方法
    
    num.toString() //  1
    
    Number(1) === 1
    
    Number(1) === new Number(1)  // false
     
    Number(1) == new Number(1)  // true
    
    1.toSting()  // 该方法会报错,因为JS无法分别.是小数点还是操作符
    
    正确做法是 const a = 1, a.toString()
    
    或者1['toString']()
    
    或者(1).toString()
     

    字符串和 布尔中道理也是一样的

    const  bol = new Boolean(false) 
    
    console.loog(bol) // Boolean{false}
    
    typeof bol // 'object'
    
    typeof Boolean(false) // 'boolean'
    
    Boolean(false) === false // true
    
    Boolean(false) === new Boolean(false) // false
    
    Boolean(false) == new Boolean(false) // true
    
    bol上同样有一个__proto__属性,指向Boolean.prototype,上面有valueOf, toString,constructor三个属性

    字符串当中

    const str = new String('str')
    
    console.log(str) // String{0: 's', 1: 't', 2: 'r'}
    
    String('str') === 'str' // true
    
    String('str') === str // false 
    
    String('str') ==  str // true
    
    str[0] === String('str')[0]
    
    str实际上是一个对象,该对象中有三个属性,还有长度属性,
    
    str.__proto__ === String.prototype 
    
    String('str').__proto__ === String.prototype

    第三部分:接下来再谈原型和原型链,就简单地多啦

    在 Javascript中,除了null,和 undefined这两个特殊的值,其他的一切都可以看做是实例对象,只是数字,字符串,布尔,symbol这样的一般不称他们为对象,

    除了null, undefined以外,所有的值都有自己的隐式原型属性__proto__,该属性指向这个值得构造函数的prototype

    看代码

    const num = 1
    
    const str = 'a'
    
    const bol = false
    
    const obj = {}
    
    const arr = []
    
    const sym = new Symbol()
    
    const set = new Set()
    
    const map = new Map()
    
    const fun = function() {}
    
    num.__proto__  ===  Number.prototype // true
    
    str.__proto__ === String.prototype // true
    
    bol.__proto__ == Boolean.prototype // true
    
    obj.__proto__ == Object.prototype // true
    
    arr.__proto__ === Array.prototype // true

    sym.__proto__ === Symbol.prototype // true map.__proto__ === Map.prototype // true set.__proto__ === Set.prototype // true fun.__proto__ === Function.prototype // true

    也就是说,任意一个数字,字符串,布尔,数组,对象,函数,set, map, symbol,都有一个__proto__属性,指向他们各自对应的构造函数

    那么 构造函数的__proto__属性会指向哪里呢?

    Number.__proto__ === Function.prototype
    
    Boolean.__proto__ === Function.prototype
    
    String.__proto__ === Function.prototype
    
    Array.__proto__ === Function.prototype
    
    Map.__proto__ === Function.prototype
    
    Set.__proto__ === Function.prototype
    
    Symbol.__proto__ === Function.prototype
    
    // 也就是说所有构造函数的原型,最终指向Function的显式原型对象
    
    那么Function.__proto__ 会指向谁呢,
    因为Function本事也属于构造函数,他的隐式原型,当然指向自身的显示原型对象
    
    Function.__proto__ === Function.prototype

    最后来讲一个特殊的,对象的__proto__属性,

    普通实例对象的__proto__属性,指向他的构造函数的prototype

    const obj = {}
    
    实际上相当于
    
    const obj = new Object()
    
    那么
    
    obj.__proto__ === Object.prototype
    
    最终问题来了,构造函数的显式原型对象,本身也是一个对象,他的__proto__会指向哪里呢?
    
    结果是
    
    除了Object构造函数以外,任意构造函数的显式原型属性的__proto__,都指向Object.prototype
    
    也就是说
    Array.prototype.__proto__ === Object.prototype
    
    Number.prototype.__proto__ === Object.prototype
    
    所有其他数据Boolean, Set, Map, Symbol, Promise等类型同理
    
    特殊的
    Function.prototype.__proto__ === Object.prototype
    
    而原型链的顶端:
    
    Object.prototype.__proto__ ===  null
    
    因为对象的显式原型对象也是一个对象,也该指向Object.prototype,
    单位了防止死循环,就把Object.prototype.__proto__ 指向了null, 也就到达了
    原型链的最顶端

    作用域链的原理:

    当一个非null, undefined类型的Javasrcipt数据想要获取某个属性值,或者调用某个方法时,如果没有该属性或者方法,那么就会向这个数据的__proto__属性中去查找,

    如果一层还没有,就回继续向上查找,最终查到Object.prototype.__proto__ 因为原型链顶端指向了null,那么就会停止。最终会返回一个undefined

    这个就是原型链的原理

    function Animal() {
        this.name = '猫'
    }
    
    Animal.name = '狗'
    
    Function.prototype.name1 = '猪'
    
    Object.prototype.name2 = '羊'
    
    const animal = new Animal()
    
    console.log(animal.name ,animal.name1, animal.name2) // 猫, undefined, 羊

    注意事项,尽量减少在prototype上增加属性或者操作,那样会修改整个作用域链, 对于JS的运行性能是一种损耗

  • 相关阅读:
    PHP 获取js中变量的方法
    Golang文件操作整理
    Golang的文件处理方式-常见的读写
    golang中文件以及文件夹路径相关操作
    服务器常用的状态码及其对应的含义
    left join on 和where条件的放置
    golang 文件导入数据追加sheet
    使用io/ioutil进行读写文件
    Go语言编程中字符串切割方法小结
    Golang学习
  • 原文地址:https://www.cnblogs.com/liquanjiang/p/11369022.html
Copyright © 2011-2022 走看看