• javascript深入浅出学习笔记


    一.数据类型:
    1.对象与对象是不相等的,比如:console.log(new Object() == new Object())//结果是false;console.log([1,2] == [1,2]);//结果是false;但是有一个例外的就是console.log(null === null)//结果是true
    2.NaN和NaN是不同的,console.log(NaN == NaN)//结果是false
    3.类型检测的几种方法:typeof、 instanceof、 Object.prototype.toString、 constructor、 duck type。
    4.typeof返回某对象的原型,typeof obj //
    5.instanceof用来判断一个对象是不是另外一个对象的实例,[1,2] instanceof Array(首字母是大写的)//结果是true
    6.Object.prototype.toString常用的几个例子:

            Object.prototype.toString.apply([]); //=== “[object Array]”;
        Object.prototype.toString.apply(function(){}); //=== “[object Function]”;
        Object.prototype.toString.apply(null); //=== “[object Null]”;

        Object.prototype.toString.apply({}); //=== “[object object]”;

        Object.prototype.toString.apply(new Date()); //=== “[object Date]”;

        Object.prototype.toString.apply(undefined); //=== “[object Undefined]”;

    7.javascrpt隐藏机制:当把一个基本类型以对象的形式去使用的时候,javascript会将其转换为包装类型对象(就是相当于new了一个对象),但是当操作完毕后这个临时包装对象就会被销毁
    var a="string";
    a.length;//6这里就会转换为包装类型对象,即相当于new String("string"),所以这里拥有length属性
    a.t=3;
    alert(a.t);//undefined,t已经被销毁了,所以是undefined
    调用它属性时会临时创建对象,调用完后就销毁,创建它的t属性时,也会创建临时对象,但创建完t属性后就销毁了,然后你再调用t属性,又会创建临时对象,但此时t是木有的.
    同样这种方法也是针对number(var nu = new Number(123)/new Number('123')对象,boolean对象的.

    二.表达式和运算符:
    1.删除对象的属性使用delete
    var obj = {x:1};
    obj.x;//1
    delete obj.x;//true
    obj.x//undefined
    但是ie9之后就会使用defineProperty这样一个方法来控制删除
    var obj = {};
    Object.defineProrperty(obj,"x",{
    configurable:false, //就是表示不能删除
    value:1
    });
    delete obj.x;//false
    obj.x; //1
    2.void运算符返回的都是undefined,比如:void(0)//undefined void("123")//undefined


    三.语句,严格模式
    1.块语句:块语句常用于组合0~多个语句,块语句用一对花括号定义.(需要注意的一点是没有块级作用域)比如:
    {语句1;语句2;...语句n},if(true){console.log(123)},for(var i=0;i<19;i++){...}等
    因为没有块级作用域,所以for(var i=0;i<19;i++){...}等价于var i=0;for(;i<29;i++){...}所以我们可以看出for循环中变量i是全局变量
    需要注意的一点是,区分函数作用域和块语句:

     函数作用域: function foo() {
        var a = 1;//这里a是局部变量,外部不可以访问
        console.log(a); // 1
        }
        foo();
        console.log(typeof a); // undefined

    块语句:
    var a = [];
    for (var i = 0; i < 10; i++) { //这里i是全局变量
      a[i] = function () {
        console.log(i);
      };
    }
    a[6](); // 因为i是全局变量,所以这里值为全局的值10
    2.try catch finally
    1.1.1 try后面至少要有catch,finally中的一个,所以就有三种方式:
          try,catch;try,finally;try,catch,finally;
    1.1.2 catch中的语句是在抛出异常之后才去执行的,当让catch中也可以抛出异常
    1.1.3 如果有finally,那么不管有没有执行catch都会执行finally的
    1.1.4 当try中发生异常时会跳到最近的catch语句中进行处理(这里就是涉及到嵌套)
    下面来看几个例子:

    try {
      try {
        throw new Error("oops");
        }
      finally {
        console.log("finally");
        }
     }
    catch (ex) {
    console.error("outer", ex.message);

    }

    执行路径:try(抛出异常) => finally(虽然抛出了异常,但是这里要先执行finally) => catch

    所以这里的结果是:"finally" "outer" "oops"

    try {
      try {
        throw new Error("oops");
        }
      catch (ex) {
        console.error("inner", ex.message);
        }
      finally {
        console.log("finally");
        }
     }
    catch (ex) {//因为上面已经执行了catch来处理异常了,所以这里的catch是不会再执行了
    console.error("outer", ex.message);
    }

    执行路径:try => catch(内部的) => finally 

    执行的结果:"inner" "oops"  "finally"

    try {
      try {
        throw new Error("oops");
      }
      catch (ex) {
        console.error("inner", ex.message);
        throw ex;//这里又抛出了异常,所以会执行最后面的那个catch
      }
      finally {
        console.log("finally");
      }
    }
    catch (ex) {
      console.error("outer", ex.message);
    }

    执行路径:try => catch(内部的) => finally => catch(外部的)
    执行结果:"inner" "oops" "finally" "outer" "oops"

    3.函数的声明function f(){...};函数的表达式var f = function f(){...};
    函数声明可以被预先处理,也可以叫函数前置,比如:
    f();//true
    function f(){...}

    fe();//TypeError
    var fe = function(){...}
    4.for in
    特点:顺序不确定,enmuerable为false时不会出现,for in对象属性时是受原型链影响
    5.switch语句:
    1.1 default是当所有的case都不满足时去执行default语句
    1.2 如果没有break语句,那么switch语句会从满足case的地方一直顺序执行到结束
    6.严格模式
    不允许未声明的变量被赋值;
    不允许使用with;
    arguments变为参数的静态副本,这里有几个重要的例子:(! function (){}(1) 表示该函数是一个函数表达式而不是函数声明,后面的(1)是将参数1传递进去,前面的!,你可以理解成它是将函数声明转化成函数表达式的一种方法。

    !function (){}(1)也等同于(function (){})(1);,!也可换成+、-这样的一元运算符,都可以起到相同的作用。

    函数也是一种对象,arguments是它的一个属性,函数的属性还包括name,length等等,arguments是参数对象的意思,不用写形参在函数上,也可以获取到函数上放进来的实参,利用arguments.length来获取参数个数,arguments[0],来获取第一个实参.)

    !function(a){
    arguments[0] = 100;
    console.log(a);//这里的结果是undefined
    }()//这里没有传入参数,所以输出的结果是undefined

    !function(){
    arguments[0] = 100;
    console.log(a);
    }(1);//这里虽然传入了参数,但是回报错,因为a没有定义

    !function(a){
    arguments[0] = 100;//非严格模式下,arguments是和传入的参数有帮定的,所以这里arguments[0]就是代表a
    console.log(a);//这里结果是100
    }(1);

    'use strict';
    !function(a){
    arguments[0] = 100;
    console.log(a);//这里结果是1,因为严格模式下,arguments成为了静态副本,不再和a有绑定
    }(1);

    'use strict';
    !function(a){
    arguments[0].x = 100;
    console.log(a.x);//这里输出来的是100,因为在严格模式下,如果传入的参数是对象的话,修改arguments属性是会对传入参数属性会影响的
    }(x:1);
    7.delete参数,函数名报错
    !function(a){
    'use strict';
    delete a;//这里会报错,如果是非严格模式下,结果为false
    }(1);
    8.delete不可配置的属性报错
    !function(a){
    'use strict';
    var obj = {};
    Object.definePrperty(obj,"a",{configurable:false});
    delete obj.a;//这里会报错TypeError
    }(1);
    9.对象字面量重复属性名报错.
    10.禁止八进制字面量.
    11.eval, arguments变为关键字,不能作为变量、函数名
    三、对象
    1、对象包含一系列的属性,这些属性是无序的,每个属性都有一个字符串key和相对应的value。
    2、对象中访问属性的顺序:某一实例对象obj => foo.prototype => Object.prototype => null,所以下面的typeof obj.toString 返回的是'function',
    当访问对象属性时,会一直按上面的方式往上面查找,如果一直没有找到,就返回undefined

    3、如果是赋值的话就不会像上面一样往上面查找,只会在本对象上查找,如果没有找到就创建一个,所以不会改变原型链上的值,同样delete可以用来删除属性,但是它只会删除本对象上的属性,不会修改掉原型链上的属性。


    4、可以使用Object.create({x:1})来创建一个对象的属性,var obj = Object.create({x:1});这句话的意思就是在原型{x:1}中创建一个对象obj,所以obj的原型是{x:1}。如果使用成这样,那么这个属性是属于(原型是)null上的,所以没有任何方法。

    5、for in 循环中因为使用的是in,所以这个循环可能会把原型链上的属性都遍历出来了,但是如果是原型链上的花只能是原型链上可以枚举的属性(一般来说原型链上的属性是不可枚举的),就是说遍历原型链上enumerable为true的属性,如果是false的,for in仍然是遍历不出来的。

    var o = {x : 1, y : 2, z : 3};

    'toString' in o; // true

    o.propertyIsEnumerable('toString');// false 我们可以使用这个方法来查看某个属性是否是可枚举的

    var key;

    for (key in o) { console.log(key); // x, y, z  这里就只会for in出可以枚举的属性

    }

    一般使用Object.create来创建的属性是可以枚举的。比如:

    var obj = Object.create(o); obj.a = 4; var key; for (key in obj) { console.log(key); // a, x, y, z }

    所以我们可以使用下面的方法来for in只属于本对象的属性。

    var obj = Object.create(o); obj.a = 4; var key; for (key in obj) { if (obj.hasOwnProperty(key)) { console.log(key); // a } }


    6、对于delete,可以用来删除对象上的一些属性,但是并非所有的属性,比如:
    1.1、delete Object.prototype;就会报错,表示不可以删除这个属性,我们可以使用var descriptor = Object.getOwnPropertyDescriptor(Object,"prototype");descriptor.configurable;//false 的方式来查看原型上的某个属性标签为true还是false来判断该属性是否是可枚举的(这里是查看Object.prototype),结果为false,所以不可以枚举。
    1.2、全局变量用var 来声明的变量不可以delete删除,但是隐式的创建变量,然后使用window的变量是可以删除的,比如:a = 1;window.a//1 delete a //true.同样声明的函数不可以删除。
    7.对象的属性标签:writable,enumerable,configurable,get/set,value等。
    8.
    2)属性操作
    对象里的属性有如下特性:
    数据属性:
    configurable:设置属性是否能被删除,属性的特性是否能被设置,能否修改属性的值等;
    enumerable:设置属性是否可枚举
    writable:设置属性的值能否被修改
    value:设置属性的值
    在添加一个对象的属性时默认上面的特性都为true,而value则是属性的值,如果想通过自定义这些特性来设置对象属性,可以通过Object.defineProperty,如下:
    var person = {name:"张三"};
    Object.defineProperty(person,name,{configurable:true,enumerable:true,writable:true,value:"李四”});
    在上面所设置的特性当中,configurable如果为false表示属性特性设置在之后不能被改动(除了writable,writable在configurable为false时仍然可以设置成false),而且configurable一旦为false后就不能再设置成true了,
    而enumberable如果为false则表示该属性不可枚举,用for in循环输出对象属性时该属性不会被输出;
    writable很明显,为false时则表示不可修改该属性的值(不过当configurable为true时可以通过修改value的值直接改写或者将writable修改为true)
    Object.defineProperty(person,name,{configurable:false});   
    delete person.name;    //delete操作不成功
    Object.defineProperty(person,name,{enumerable:false});  //操作不成功
    ...
    访问器属性
    configurable:设置属性是否能被删除,属性的特性是否能被设置,能否修改属性的值等;
    enumerable:设置属性是否可枚举
    get / set :在读写属性时会自动调用的函数
    比如:
    var book = {
       _year:2004,
       edition:1
    };
    Object.defineProperty(book,"year",{
       get:function(){
            return this._year;
       },
       set:function(newValue){
           this._year = newValue;
           this.edition += newValue - 2004;
       }
    });
     
    book.year = 2005; //当要设置year属性时,会自动调用set方法
    alert(book.edition);
     
    如果要的不止是配置单单一个属性,而是要同时配置多个,可以通过Object.defineProperties,如下:
    var person = {name:"张三"};
    Object.defineProperty(person,{
          name:{value:"李四”,configurable:false},
          sex:{value:"man",writable:false}
    });
    在配置完属性后或者通过Object.defineProperty更改过属性后想读者该属性,可以通过Object.getOwnPropertyDescriptor读取
    Object.getOwnPropertyDescriptor(book,"edition");        //读取book对象中的edition属性
     
     
    3)对象标签
    [[proto]]:
    对象中有个属性[[proto]]指向它的构造器的原型
     
    [[class]]:
    看不懂视频里在讲啥- -,没说为啥是通过Object.prototype.toString去获取[[class]]的,所以还是不懂[[class]]的含义
     
    [[extensible]]:
    var obj = {x:1,y:2};
    Object.isExtensible(obj);   //检测对象是否可扩展,一般来说默认都是true
    Object.preventExtensions(obj);  //禁止对象可扩展
    Object.defineProperty(obj,"x",{value:2});   //虽然禁止了对象扩展,但是删除或者修改属性的值以及标签
    Object.seal(obj);   //禁止对象属性被删除以及配置属性标签
    Object.isSealed(obj);   //判断对象是否被seal
     
    Object.freeze(obj); //冻结对象,禁止对象属性值被改写
    Object.isFrozen(obj);   //判断对象是否被freeze
     
    4)序列化
    在向后台发送请求数据时,用JSON.stringify将对象转化为字符串,用JSON.parse将字符串解析为对象
    但是,在用JSON.stringify将对象转化为字符串时如果对象属性的值为undefined,那么它将不会出现在转化后的字符串里
    如果我们想自定义序列化,可以在对象里自定义toJSON方法,同理,我们在将对象toString或者valueOf时也可以自定义toString方法和valueOf方法
     
    对象转化为基本类型的过程:
    在后台首先会自动调用valueOf方法尝试将对象转化为基本类型,如果valueOf不存在或者无法转化为基本类型则会调用toString方法继续尝试,如果两种都无法将对象转化为基本类型则会报错
     总结来看:继承的几种方法:
    function Person(){}
    funciton Student(){}
    Student.prototpe.constructor = Student;
    1.Student.prototype = new Person();//传参可能有问题
    2.Student.prototype = Person.prototype;//这种方法的缺点就是父类和子类的原型都指向了同一个对象,如果改变一个会导致两个都受影响
    3.Student.prototype = Object.create(Person.prototype);//注意这种方法是要在ES5之后才能用,但是时最实用的,所以我们引出了第四种
    4.if(!Object.create){
    Object.create = function(proto){
    function F(){}
    F.prototype = proto;//proto是原型对象
    retrun new F;
    };
    }
  • 相关阅读:
    java图书管理系统界面版本+mysql数据库
    java数组实现的超市管理系统(控制台)
    Action<T>和Func<T>委托事例
    简单的委托示例
    使用静态方法CreateInstance()创建数组
    Span复习
    与预定义类型的用户类型强制转换
    实现自定义的索引运算符
    比较运算符的重载
    算术运算符的重载
  • 原文地址:https://www.cnblogs.com/fireporsche/p/6560270.html
Copyright © 2020-2023  润新知