• Javascript (ECMAScript5) 的细节和违反直觉的地方


    记录在学习Javascript (ECMAScript5) 中的一些与其他语言的不同之处,本文会不断更新。

    里面的知识可能并不太适合有一定经验的Javascript程序员,仅仅但不限于给初学者阅读。

     

     1. null 是一个表示“空”的对象指针

    var foo = null
    console.log(typeof foo)  //输出 object 而不是你所认为的 null

     

     2. undefined 是 null 派生而来的

    console.log(null == undefined)  //输出 true

     

     3. 浮点数值计算误差问题

    var a = 0.1
    var b = 0.3
    if (a+b == 0.3){
         alert('OK')  //然而a+b将会等于 0.300000000000000004
    }

     

    当然不仅仅只是ECMAscript有这种问题,很多使用相同数值类型的也有

    4.NaN 不等于任何值,包括自身

    NaN == NaN //false
    NaN == "NaN" //false
    NaN == 0 //false
    //当然了你可以使用 isNaN 函数

     

    5.for in 语句是没有顺序的代送

    6.switch 可以是任何对象比较,不同与 C/C++ 或 Java 7 等里面不能字符串比较

    7.所有函数的参数传参都是按值传的,哪怕传入的是对象,也会复制引用指针

    function setName(obj){  //这个obj 是复制的引用指针,指向A
         obj.name = 'OneName'
         obj = new Object(); //B  但是现在你改变了这个复制的引用指针 指向B
         obj.name = 'TwoName'    //设置的仅仅是B
    }
    
    var p = new Object() // A
    setName(p)
    alert(p.name) // 输出 OneName

     

    8.Javascript 没有块级作用域(暂时不讨论闭包等)

    你可能认为 两个{}大括号之间属于作用域区,这是Java的经验,然而在Javascript这点并没有得到实现

     

    if (true){
         var name = 'YouName' ;
    }
    alert(name); // 依然可以得到输出 YouName
    for(var i=0;i<5;i++){
         i++;
    }
    alert(i); //依然可以得到 变量 i

     

    9.使用对象字面量表示法定义的对象,实际上将不会调用Object构造函数,推荐只用于只读的业务使用。

    var p = {}; // 与 new Object() 得到的结果相同,但不会调用构造函数
    p.name = 'YouName'; //依然可以想类一样操作
    
    var obj = {
        name: 'Name'
        die: function(){//foo}
    } //一样

     

    10. 直接指向对象,而不是指向下一个引用

    var A = function(){
        alert('Run');
    }
    var C = A;
    A = null;   //链表的经验可能会告诉我们C将会失效指向null
    C() //依然正常运行,不影响

     

    11.谜一般的 this 指针究竟指向什么?

    function func (A,B){  
         alert(this)  
         return A+B;
    }
    var A = 1;
    var B = 2;
    func(A,B); //调用函数 alert输出 window
    //事实上这就相当于默认调用了 this值将会绑定到 global
    func.call(window,A,B) //alert输出 window
    func.call(undefined,A,B) //alert输出 undefined
    func.apply(new Object(),[A,B]) //输出 Object
    //这个第一项参数就是this值

     在不同环境下执行函数将得到不同的this值,这里是全局环境,所以this绑定到全局global对象,所以直接调用将是window,如果你再其他环境下调用,那么就将是其他值了。

    如果你这样,函数有所属对象时,this绑定到所属对象上去

    var obj = new Object();
    obj.fun = function(){ console.log(this); }
    obj.fun(); //调用,此时this值将绑定到 obj 上面去,即this就是obj

     所谓绑定,其实就是 function所有的bind() 函数。

    var o = {color:'red'};
    function sayColor()
    {
        console.log(this.color);
    }
    window.color='undefined'
    var A = sayColor.bind(o);  //一旦你这样显式的绑定了之后,不论环境怎么样,一定是你绑定的对象为this
    A()  //这里会输出 red 而不是 全局对象color的 undefined

     让我们回到this主题:

    情况一:普通的函数调用( func(A,B,C,D,....); ) this绑定到全局global 对象。

    情况二:作为对象方法的调用 ( obj.func(A,B,C,...) )  this绑定到所附属的对象上。

    情况三:作为构造函数调用(var obj = new YourObject())  this绑定到新构造出现的对象(obj)上。

    情况四:显示绑定(bind apply call等) this绑定到你指定的对方。

     

    12. 属性会覆盖掉原型的属性,当属性被删除之后,原型的属性又会重新恢复

    Array.prototype.name = "A";
    var obj = new Array();
    obj.name //输出A
    obj.name = "B"
    obj.name//输出B
    delete obj.name 
    obj.name //输出A 而不会是 undefined

    13. 完全重写原型不会在现有的实例上体现

    var A = function(){};
    A.prototype = {
      name:'YOU'  
    }
    
    var obj = new A();
    obj.name // 输出 YOU
    
    //然后我们重写原型
    A.prototype = {//这一次修改的原型将不会应用到已经实例化的原型中
      name:'ME'  
    }
    obj.name //依然 输出 YOU
  • 相关阅读:
    如何写出SpringBoot官方模样的Starter
    VS Code调试go语言程序
    redis 数据持久化,主从,哨兵等
    注解方式结合spring aop实现日志动态可插拔打印
    BeanUtils.copyProperties()的一个坑
    视频转换工具
    数库移表移行后如何对比数据呢
    XPS VIEWER FOR WIN10的安装方法
    增加注册表键值的命令
    .net web开发
  • 原文地址:https://www.cnblogs.com/suwings/p/6284871.html
Copyright © 2020-2023  润新知