zoukankan      html  css  js  c++  java
  • JavaScript 随笔

     js 内置 7种类型

    基本类型: string number boolean null undefined symbol 
    
    引用类型: object

    typeof 可判断除 null 外所有   基本类型  

    typeof null // 'object'
    //JS 的最初版本中 使用的是 32 位系统,为了性能考虑使用低位存储了变量的类型信息,000 开头代表是对象,然而 null 表示为全零,所以将它错误的判断为 object
    //undefined 不是保留字,能够在低版本浏览器被赋值
    //判断一个值是否等于 undefined 
    a === void 's'

    可通过Object.prototype.toString.call() 判断一个变量的正确类型


    类型转化

    在条件判断时,除了 undefined, null, false, NaN, '', 0, -0,其他所有值都转为 true,包括所有对象。

    对象在转换基本类型时,首先会调用 valueOf 然后调用 toString。并且两个方法可以重写

    let a = {
      valueOf() {
        return 0;
      },
      toString() {
        return '1';
      },
      [Symbol.toPrimitive]() {//优先级最高
        return 2;
      }
    }
    a.valueOf() //0
    a.toString() // '1'
    1 + a // => 3
    '1' + a // => '12'

    操作符

    加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串。

    一方是字符串类型,会把另一个也转为字符串类型。

    一方是数字, 另一方就转为数字。优先级 string>number

    '1' + + '' //"10"
    '1' ++ '' //Error
    + '' //0

    toPrimitive(obj)等价于:先计算obj.valueOf(),如果结果为原始值,则返回此结果;否则.计算obj.toString(),如果结果是原始值,则返回此结果;否则,抛出异常

    比较运算符

    如果是对象,就通过 toPrimitive 转换对象 如果是字符串,就通过 unicode 字符索引来比较

    "=="规则
    x,y 类型相同:
        x -> undefined    //true
        x -> null  //true
        x -> number 
             x -> NaN  //false
             y -> NaN  //false
             x == y   //true
             x -> +0 && y -> -0 //true
             x -> -0 && y -> +0 //true
        x -> string ,x和y 字符序列完全相同<长度相等,相同字符位置相同>   //true
        x -> Boolean  x&&y = true/false  //true
    x和y 引用 同一对象 //true
    x -> null , y -> undefiend //true
    x -> undefiend , y -> null //true
    x -> number ,y -> string    Number(y)  ==>参考上文 x -> number
    x -> string , y ->number   Number(x)  ==> 参考上文 x -> number
    x -> Boolean  Number(x)  ==> 参考上文 x -> number
    y -> Boolean  Number(y)  ==> 参考上文 x -> number
    x -> string || number, y -> object  x ==toPrimitive(y)
    x -> object && y ->string || number toPrimitive(x) ==y
    [] == ![] //右: ![] 转成 true,然后取反变成 false
    //左: ToPrimitive([]) == 0
    // [].toString() -> ''
    //结果为true

    Prototype

    原型链:

     
     
    1. 实例通过__proto__ 访问对应构造函数的原型 -> B.prototype
    2. 函数原型 通过__proto__ 访问Object的原型 -> Object.prototype
    3. Object的原型的__proto__ 指向 null
    4. 构造函数 Object.prototype 通过constructor访问构造函数本身 每个构造函数通过 prototype 访问原型

     

     基本上所有函数都有这个属性 (只有函数才拥有prototype属性) ,有一个例外

    let fun = Function.prototype.bind()

    当声明一个函数时自动创建 prototype 属性, 这个属性的值是一个对象(也就是原型),只有一个属性 constructor;

    constructor 是一个公有且不可枚举的属性。一旦我们改变了函数的 prototype ,那么新对象就没有这个属性了(当然可以通过原型链取到 constructor)。

    function A(){}
    console.log(A.prototype) // {constructor: ƒ}constructor: ƒ A()__proto__: Object
    A.prototype="a"
    console.log(A.prototype) //"a"

    constructor作用:

    • 让实例对象知道是什么函数构造了它
    • 如果想给某些类库中的构造函数增加一些自定义的方法,就可以通过 xx.constructor.method 来扩展
    __proto__

    每个对象都有的隐式原型属性,指向创建该对象的构造函数的原型,实际指向[[prototype]], 内部属性,我们并不能访问到所以使用 proto 来访问。

    console.log({})
    //__proto__: Objectconstructor: ƒ Object()hasOwnProperty: ....

    当我们使用 new 操作符时,生成的实例对象拥有了 __proto__属性。

    function Foo() {}
    // 这个函数是 Function 的实例对象
    // function 就是一个语法糖
    // 内部调用了 new Function(...)

    所有对象都可以通过原型链最终找到 Object.prototype ,虽然 Object.prototype 也是一个对象,但是这个对象却不是 Object 创造的,而是引擎自己创建了 Object.prototype 。

    所以可以这样说,所有实例都是对象,但是对象不一定都是实例。

    首先引擎创建了 Object.prototype ,然后创建了 Function.prototype ,并且通过__proto__ 将两者联系了起来。

    Function.prototype 以后才有了 function Function() ,然后其他的构造函数都是 function Function() 生成的

    函数通过 new Function() 生成, 不是所有函数都是 new Function() 产生的。


    1. Object 是所有对象的爸爸,所有对象都可以通过__proto__ 找到它
    2. Function 是所有函数的爸爸,所有函数都可以通过__proto__ 找到它
    3. Function.prototype 和 Object.prototype 是两个特殊的对象,他们由引擎来创建
    4. 除了以上两个特殊对象,其他对象都是通过构造器 new 出来的
    5. 函数的 prototype 是一个对象,也就是原型 对象的__proto__ 指向原型,__proto__将对象和原型连接起来组成了原型链

    new 的过程

    新生成了一个对象 链接到原型 绑定 this 返回新对象

    function create() {
        // 创建一个空的对象
        let obj = new Object()
        // 获得构造函数
        let B = [].shift.call(arguments)
        // 链接到原型
        obj.__proto__ = B.prototype
        // 绑定 this,执行构造函数
        let result = B.apply(obj, arguments)
        // 确保 new 出来的是个对象
        return typeof result === 'object' ? result : obj
    }

    实例对象,都是通过 new 产生的,无论是B() 还是obj 。

     所有运算圆括号优先级最高 成员 - 计算 从左至右访问 

    new F1.getName();   //-->new (F1.name());
    new F1().getName(); // -->(new F1()).name();

     

     

    instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype

    function objType(left, right) {
        // 获得类型的原型
        let prototype = right.prototype
        // 获得对象的原型
        left = left.__proto__
        // 判断对象的类型是否等于类型的原型
         if (left === null)
                return false
            if (prototype === left)
                return true
            left = left.__proto__
     }

    执行上下文

    当执行 JS 代码时,会产生三种执行上下文

    • 全局执行上下文
    • 函数执行上下文
    • eval 执行上下文
    arguments 是函数独有的对象(箭头函数没有)
    作用域链,可以把它理解成包含自身变量对象和上级变量对象的列表,通过 [[Scope]] 属性查找上级变量
    在生成执行上下文时,会有两个阶段。
    函数和变量提升
    第一个阶段是创建的阶段,JS 解释器会找出需要提升的变量和函数,并且给他们提前在内存中开辟好空间,函数的话会将整个函数存入内存中,变量只声明并且赋值为 undefined,
    第二个阶段,也就是代码执行阶段,我们可以直接提前使用。

    在提升的过程中,相同的函数会覆盖上一个函数,并且函数优先于变量提升
    b() // 1
    
    function b() {
        console.log('2')
    }
    function b() {
        console.log('1')
    }
    var b = 'Hello world'

     

     

     

  • 相关阅读:
    Asp.net MVC企业级开发(01)---Autofac
    3°、6°带高斯-克吕格投影
    使用html2canvas实现网页截图并嵌入到PDF
    中国UTM分区
    遇到乱码不怕不怕啦——计算机字符编码详尽讲解
    ArcGIS Engine10.2如何安装在 VisualStudio2013 开发环境下
    【OSG学习笔记之一:】OSG+VS2010+win7 64位环境搭建
    Python回调函数用法实例详解
    python下编译py成pyc和pyo
    ERDAS文件格式:IGE、IMG、RRD、AUX
  • 原文地址:https://www.cnblogs.com/gaoguowen/p/10082526.html
Copyright © 2011-2022 走看看