• 理解js的几个关键问题(1):全局变量new和关于hasOwnPropery和PropertyIsEnumerable 等


    一、作用域和全局变量

    var test=function(){
        var a=1;
        setTimeout(function(){
            console.log(a);
            a=2;
        },1000);
        a=3;
        setTimeout(function(){
            console.log(a);
            a=4;
        },2000);
     
    };
    test();

    结果是3,2;

    共享内存。setTimeout等异步,是取现在当时的a的值。执行第一个setTimeout的时候,a=3,已经执行了。

     二、全局变量和new变成全局的

    var foo=10;
    var a=1;
    var  main = function (){
    //a=10;
    console.log(a);
    a=20;
    console.log(this.foo);
    this.foo=foo;
    console.log(this.foo);
    foo=1000;
    console.log("111111111111");
    }
    var s=main();
    var d=new main();

    1

    10

    10

    111111111111

    20

    undefined

    1000

    111111111111

    不加new 都是全局的,this指向的全局变量。所以第一个就取得是全局的值。

    第二个加new 了,this.foo指向的是自己,没有定义于是就报undefined。外面a foo等是全局变量,main(),执行后,a已经变成20了,foo也变成1000了,所以值发生变化了,因为全局变量。

    var foo=10;
    var a=1;
    var  main = function (){
    //a=10;
    console.log(a);
    a=20;
    console.log(this.foo);
    this.foo=foo;
    console.log(this.foo);
    foo=1000;
    console.log("111111111111");
    }
    //var s=main();
    var d=new main();

    如果不执行第一个,结果发生变化。可以发现其实是全局变量的修改。

    undefined

    10

    111111111111

    三、快速的判断Array类型

     var toString = Object.prototype.toString;
      var isArray = Array.isArray || function(val) {
        return toString.call(val) === '[object Array]';
      };
    
      function isString(val) {
        return toString.call(val) === '[object String]';
      }
    
      function isFunction(val) {
        return toString.call(val) === '[object Function]';
      }

    四、attribute和Property的区别

    attribute

    input节点有很多属性(attribute):‘type’,'id','value','class'以及自定义属性,在DOM中有setAttribute()和getAttribute()读写DOM树节点的属性(attribute)

    PS:在这里的getAttribute方法有一个潜规则,部分属性(input的value和checked)通过getAttribut取到的是初始值,这个就很好的解释了之前的n1为1。

    Property

    javascript获取到的DOM节点对象,比如a 你可以将他看作为一个基本的js对象,这个对象包括很多属性(property),比如“value”,“className”以及一些方法,setAttribute,getAttribute,onclick等,值得注意的是对象的value的属性(property)取值是跟着输入框内的当前值一起更新的,这解释了之前的n2为什么为1000了。

    五、关于hasOwnPropery和PropertyIsEnumerable 

    参考:http://www.zhihu.com/question/21262706/answer/17691563

    var aaa = {
        a: 123,
        b: 456
    }
    var BBB = function (){};
    BBB.prototype = aaa;
    BBB.prototype.c = 789;
    var bbb = new BBB();
    console.log(bbb);
    for (var i in bbb){
        if(bbb.hasOwnProperty(i) ){
            console.log(i);
            console.log(bbb[i]);    
        }
    }

    BBB {a: 123, b: 456, c: 789}

    里面的hasOwnProperty没有执行,因为都是别人的,不是自己的。

    var aaa = {
        a: 123,
        b: 456
    }
    var BBB = function (){
        this.c = 789;    
    };
    BBB.prototype = aaa;
    BBB.prototype.d = 0;
    var bbb = new BBB();
    bbb.e=function(){};
    bbb.f="abc";
    console.log(bbb);
    for (var i in bbb){
        console.log("hasOwnProperty "+bbb.hasOwnProperty(i));
        if(bbb.hasOwnProperty(i)){
            console.log(i);
            console.log(bbb[i]);    
        }
        console.log("propertyIsEnumerable "+bbb.propertyIsEnumerable(i));
        if(bbb.propertyIsEnumerable(i)){
            console.log(i);
            console.log(bbb[i]);    
        }
    }
    BBB {c789efunctionf"abc"a123b456}
    test.html:19
    hasOwnProperty true test.html:21
    propertyIsEnumerable true test.html:26
    hasOwnProperty true test.html:21
    function (){} test.html:24
    propertyIsEnumerable true test.html:26
    function (){} test.html:29
    hasOwnProperty true test.html:21
    propertyIsEnumerable true test.html:26
    hasOwnProperty false test.html:21
    propertyIsEnumerable false test.html:26
    hasOwnProperty false test.html:21
    propertyIsEnumerable false test.html:26
    hasOwnProperty false test.html:21
    propertyIsEnumerable false

     
    总结:表现的一致。共同点是都不能便利到继承过来的,也就是prototype上的属性,function 一样能够被判断为true。语言精粹中提示可以用typeof bbb[i] !=="function"。
    针对继承都没有,放在property上的也都没有。
    每个对象都有propertyIsEnumerable方法.该方法可以判断出指定的属性名是否是自身的可枚举属性,也就是说该属性是否可以通过for...in循环等遍历到,不过有些属性虽然可以通过for...in循环遍历到,但因为它们不是自身属性,而是从原型链上继承的属性,所以该方法也会返回false.
    注:从JavaScript 1.8.1(Firefox 3.6)开始, propertyIsEnumerable("prototype")返回false,而不是以前的true,这是为了符合ECMAScript 5规范.
    由于 for ... in 枚举是包含原型链上的属性的,会把c789a123b456d0等全部都打印出来。
    值得注意的是,propertyIsEnumerable对继承来的属性一律判断为false,这一般被认为是ECMA Script 规范的一个设计上的错误。
     
    所以如果你只想遍历对象本身的属性,可以:

    for (var key in obj) {
      if (obj.hasOwnProperty(key) {
       ...
      }

    反过来说,没有必要在 for ... in 中去检测 propertyIsEnumerable,因为不可枚举的属性是不会 for...in 出来的。

    propertyIsEnumerable这个方法其实用到的场合非常少,基本上已经被Object.getOwnPropertyDescriptor取代。唯一区别是,后者只能得到own property是否enumerable,而前者包含了整个原型链。
    用法如下
    Object.getOwnPropertyDescriptor(bbb, i)
    返回 getOwnPropertyDescriptor [object Object]

    参考:http://www.cnblogs.com/guoyansi19900907/p/3730511.html

    hasOwnProperty().方法用来检测给定的名字是否是对象的只有属性.对于继承属性它将返回false  

    1  var o={x:1};
    2         console.log(o.hasOwnProperty("x"));//true.
    3         console.log(o.hasOwnProperty("y"));//false
    4         console.log(o.hasOwnProperty("toString"));//false

    propertyIsEnumerable()是hasOwnProperty()的增强版,只有检测到是只有属性且这个属性的可枚举为true是它才返回true.

    1 var obj=Object.create(o);
    2         obj.xx=1;
    3         console.log(obj.propertyIsEnumerable("x"));//false
    4         console.log(obj.propertyIsEnumerable("xx"));//true
    5         console.log(Object.prototype.propertyIsEnumerable("toString"));//false
     
  • 相关阅读:
    生成器
    装饰器
    类的特殊方法
    获取对象的信息之反射
    获取对象信息之内置函数dir()
    获取对象的信息之内置函数type()
    获取对象的信息之内置函数issubclass() 和 isinstance()
    生成可下载图片
    js数组常用方法
    sql存储过程基本语法
  • 原文地址:https://www.cnblogs.com/danghuijian/p/3729479.html
Copyright © 2020-2023  润新知