美文网首页%……%菜鸟程序员成长记
javascript高级程序设计(第三版)读书书笔记(一)

javascript高级程序设计(第三版)读书书笔记(一)

作者: 2857b61e8161 | 来源:发表于2017-11-12 11:19 被阅读32次

    《JavaScript高级程序设计》(第三版)这本红皮书应该是很有名了,买这本有一年了,断断续续的看了前七章,收获很多。趁着周末,刚好把之前记的纸质笔记记录到简书上。

    1、如果在函数中使用var定义一个变量,是局部变量,如果省略了var就是全局变量。

    function test() {
      var message = "hi"; //局部变量
    }
    test();
    alert(message);//报错
    
    function test2() {
    message2 = "hi";//全局变量
    }
    test2();
    alert(message2);//hi
    

    2、五种基本数据类型:Undefined Null Boolean Number String,还有一种复杂数据类型Object。

    3、typeof:检测给定变量的数据类型。

    typeof null //object
    

    4、Undefined类型:使用var声明变量,但为对其初始化时。

    5、Null类型:只有一个值null。空对象指针。如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null,这样只要检查null值就可以知道相应的变量是否已经保存了一个对象的引用。

    var car = null;
    if(car!=null) {
     对car对象执行某些操作
    }
    
    alert(undefined==null);//true
    

    6、Boolean类型:有两个值true和false,这两个值与数字值不是一回事,因此true不一定等于1,而false不一定等于0。对任何数据类型的值调用 Boolean()函数,而且总会返回一个Boolean值。

    Boolean(0);//false
    Boolean("");//false
    Boolean(NaN);//false
    Boolean(undefined);//false
    Boolean(null);//false
    

    7、NaN:非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数为返回数值的情况。任何数值除以非数值会返回NaN。NaN与任何值都不相等,包括NaN本身。

    8、数值转换:有三个函数可以把非数值转换为数值:Number()、parseInt()和parseFloat(),第一个函数可以用于任何数据类型,而另外两个函数则专门用于把字符串转换成数值。

    Number(true);//1
    Number(false);//0
    Number(null);//0
    Number(undefined);//0
    Number("123");//123
    Number("011");//11
    Number("");//0
    Number("hi");//NaN
    
    parseInt("1234blue");//1234
    parseInt("");//NaN
    parseInt(22.5);//22
    
    parseFloat("1234blue");//1234
    parseFloat("0xA");//0
    parseFloat("22.5");//22.5
    parseFloat("22.5.5");//22.5
    

    9、String类型:

    String(null);//"null"
    String(undefined);//"undefined"
    

    10、Object类型:创建Object实例的方式有两种,第一种是使用new操作符后跟object构造函数,第二种是对象字面量表示,Object的每个实例都具有下列属性和方法:

    var o = new Object();
    var person = {
      name:"kele",
      age:18
    }
    

    constructor:保存着用于创建当前对象的函数,上面例子,constructor就是Object()。

    hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是实例的原型中)是否存在。o.hasOwnProperty("name")

    isPrototypeOf(object):用于检查传入的对象是否是当前对象的原型。

    propertyIsEnumberable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。

    toLocalString():返回对象的字符串表示。
    toString():返回对象的字符串表示。
    valueOf():返回对象的字符串、数值或布尔值表示。

    11、逻辑与:逻辑与操作可以用于任何类型的操作数,而不仅仅是布尔值。在有一个值不是布尔值的情况下,逻辑与操作就不一定返回布尔值,此时遵循下列规则:

    • 如果第一个操作数是对象,则返回第二个操作数;
    • 如果第二个操作数是对象,则只有在第一个操作数的求值结果为true的情况下才会返回该对象。
    • 如果两个操作数都是对象,则返回第二个操作数。
    • 如果第一个操作数是null,则返回null。
    • 如果第一个操作数是NaN,则返回NaN。
    • 如果第一个操作数是undefined,则返回undefined。
      逻辑与操作属于短路操作,如果第一个操作数能够决定结果,那么就不会再对第一个操作数求值。
    var a = true;
    var result = a && b;/会报错,因为b未声明
    alert(result);//这一行不会执行
    
    var b = false;
    var c = b && d;
    alert(c);//false
    
    

    12、逻辑或:

    • 如果第一个操作数是对象,则返回第一个操作数。
    • 如果第一个操作数的求值结果为false,则返回第二个操作数。
    • 如果两个操作数都是对象,则返回第一个操作数;
    • 如果两个操作数都是null,则返回null。
    • 如果两个操作数都是NaN,则返回NaN。
    • 如果两个操作数都是undefined,则返回undefined。
      逻辑或操作符是短路操作,如果第一个求值的结果是为true,就不会对第二个操作数求值了。
    var a = true;
    var result = a || b;
    alert(result);//true
    
    var b = false;
    var c = b || d;//报错
    alert(c);//不执行
    

    13、break和continue语句:break语句立即退出循环强制继续执行循环后面的语句,而continue会退出循环之后会从循环的顶部继续执行。

    var num = 0;
    for(var i=1;i<10;i++){
      if(i%5==0) {
          break;
    }
      num++
    }
    alert(num);//4
    
    var num =0;
    for(var i=1;i<10;i++){
      if(i%5==0){
        continue;
    }
    num++;
    }
    alert(num);//8
    

    14、函数:用function关键字来声明,函数会在执行完return语句之后停止并立即退出,return之后的任何代码永远不会执行。函数体内可以通过arguments对象访问参数数组,从而获取传递给函数的每一个参数。可以向函数传递任意数量的参数。

    function howManyArgs() {
      alert(arguments.length);
    }
    howManyArgs("string",45);//2
    howManyArgs();//0
    

    arguments对象中的值会自动反映到对应的命名参数上。

    function test(num1,num2) {
      arguments[1]=10;
      alert(arguments[0]+num2);
    }
    

    每次执行test()函数都会重写第二个参数,将第二个参数修改为10,因为arguments对象中的值会自动反映到对应的命名参数,所以修改arguments[1],也就修改了num2。这并不是说读取这两个值会访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。如果只传入了一个参数,那么为arguments[1]设置的值不会反映到命名参数中,因为arguments对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。
    未指定返回值的函数返回的是一个特殊的undefined。

    15、函数没有重载,定义了两个名字相同的函数,则该名字只属于后定义的函数。

    function test(num) {
      return num+100;
    }
    function test(num) {
      return num+200;
    }
    var result = test(100); //300
    

    16、变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,引用类型指的是由多个值构成的对象。

    17、复制变量值:引用类型和基本类型值除了保存的方式不同之外,在从一个变量向另一个变量复制时,也存在不同。如果从一个变量向另一个变量复制基本数据类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。

    var num1 = 5;
    var num2 = num1;
    

    在num1中保存的是5,当使用num1初始化num2时,num2中也保存了5。但num2中的5与num1中的5是完全独立的。

    当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象的值复制一份放到新变量分配的空间中。不同的是,这个值的副本是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。

    var obj1 = new Object();
    var obj2 = obj1;
    obj1.name = "kele";
    alert(obj2.name);//kele
    

    18、传递参数:ECMAScript中所有函数的参数都是按值传递的。把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。

    function test(num){
      num += 10;
      return num;
    }
    var count = 20;
    var result = test(count);
    alert(count);//20 没有变化
    alert(result);//30
    
    
    function setName(obj) {
        obj.name = "kele";
    }
    var person = new Object();
    setName(person);
    alert(person.name);//"kele"
    
    function setName2(obj) {
      obj.name = "hi";
      obj = new Object();//引用的局部对象
      obj.name = "hello";
    }
    
    var person2 = new Object();
    setName2(person2);
    alert(person2.name);//"hi"
    

    19、instanceof:检测引用类型的值。在检测一个引用类型值和Object构造函数时,instanceof操作数始终会返回true。如果检测基本数据类型的值,则返回false。

    alert(a instanceof Object);
    alert(a instanceof Array);
    

    20、垃圾收集:javascript具有自动垃圾收集机制,javascript中最常用的垃圾收集方式是标记清除。另一种叫做引用计数。

    21、执行环境有全局执行环境和函数执行环境,全局环境只能访问在全局环境中的变量和函数,局部环境不仅有权访问函数作用域中的变量,还可以访问包含父环境乃至全局环境。

    22、使用不带圆括号的函数名是访问函数指针,而非调用函数。

    function sum(num1,num2){
      return num1 + num2;
    }
    alert(sum(10,10));//20
    
    var anotherSum = sum;
    alert(anotherSum(10,10));//20
    
    sum=null;
    alert(anotherSum(10,10));//20
    

    23、函数声明与函数表达式的区别:解析器会率先读取函数声明,并使其在执行任何代码之前可以调用,函数表达式则必须等到解析器执行到它所在的代码行,才会真正被执行。

    alert(sum(10,10));//20 正常执行
    function sum(num1,num2) {
     return num1+num2;
    }
    
    alert(test(20,20));//会报错
    var test = function(num1,num2) {
     return num1+num2;
    }
    

    24、作为值的函数:不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。例如,假设有一个对象数组,我们想要根据某个对象属性对数组进行排序。而传递给数组sort()方法的比较函数要接收两个参数,即要比较的值。可是,我们需要一种方式来指明按照哪个属性来排序。要解决这个问题,可以定义一个函数,它接收一个属性名,然后根据这个属性名来创建一个比较函数。

    function createCompareFunction(propertyName){
      return function(object1,object2){
        var value1 = object1[propertyName];
        var value2 = object2[propertyName];
    
        if(value1 < value2) {
            return -1;
        }else if(value1>value2){
            return 1;
        }else{
            return 0;
        }
    
      }
    }
    
    var data = [{name:"Zachary",age:28},{name:"Nicholas",age:29}];
    data.sort(createCompareFunction("name"));
    alert(data[0].name);//Nicholas
    
    data.sort(createCompareFunction("age"));
    alert(data[0].name);//Zachary
    

    25、函数内部属性:函数内部有两个特殊的对象:arguments和this。其中,arguments是一个类数组对象,包含着传入函数中的所有参数。这个对象还有一个callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。

    function test(num) {
      if(num<=1){
      return 1;
    }else{
      return num*arguments.callee(num-1);
     }
    }
    var test2 = test;
    test = function() {
      return 0;
    }
    alert(test2(5));//120
    alert(test(5));//0
    
    window.color = "red";
    var o = {color:"blue"};
    
    function sayColor(){
      alert(this.color);
    }
    sayColor();//"red"
    o.sayColor();//blue
    

    函数的名字仅仅是一个包含指针的变量而已。因此,即使是在不同的环境变量中执行,全局的sayColor()函数

    25、ECMAScript5规范了函数对象的属性:caller。这个属性中保存着调用当前函数的函数的引用,如果是在全局函数中调用当前函数,它的值为null。

    function outer(){
      inner();
    }
    
    function inner(){
      alert(inner.caller);
    }
    outer();
    

    以上代码会导致警告框中显示outer()函数的源代码。因为outer()调用了inner(),所以inner.caller就指向了outer()。也可以通过arguments.callee.caller来访问相同的信息。

    function outer() {
      inner();
    }
    function inner() {
      alert(arguments.callee.caller);
    }
    outer();
    

    当函数在严格模式下运行,访问 arguments.calleearguments.caller会导致错误。严格模式下不能为caller属性赋值,否则会导致错误。

    26、ECMAScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:lengthprototypelength属性表示函数希望接收的命名参数的个数。

    function sayName(name){
      alert(name);
    }
    
    function sum(num1,num2){
    return num1+num2;
    }
    
    function sayHi(){
    alert("hi");
    }
    alert(sayName.length);//1
    alert(sum.length);//2
    alert(sayHi.length);//0
    

    27、对ECMAScript中的引用类型,prototype是保存它们所有实例方法的真正存在,toString()方法和valueOf()等方法都保存在prototype中,通过各自对象的实例访问。ECMAScript5中,prototype属性是不可枚举的。

    28、每个函数都包含两个非继承而来的方法:apply()call()。两个方法的用途都是在特殊作用域中调用函数,实际上等于设置函数体内this对象的值。首先apply()方法接收两个参数:一是在其中运行函数的作用域,另一个是函数数组。其中,第二个参数可以是Array的实例,也可以是arguments对象。

    function sum(num1,num2){
      return num1+num2;
     }
    function callSum1(num1,num2){
      return sum.apply(this,arguments);//传入arguments对象
    }
    function callSum2(num1,num2){
      return sum.apply(this,[num1,num2]);//传入数组
    }
    alert(callSum1(10,10));//20
    alert(callSum2(10,10));//20
    

    29、call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对象call()方法,第一个参数是this没有变化,变化的是其余参数都直接传递给函数。在使用call()方法时,传递给函数的参数必须逐个列举出来。

    function sum(num1,num2){
      return num1+num2;
    }
    function callSum(num1,num2){
      return sum.call(this,num1,num2);
    }
    alert(callSum(10,10));//20
    

    传递参数并非apply()call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。

    window.color = "red";
    var o = {color:"blue"};
    function sayColor(){
      alert(this.color);
    }
    sayColor();//red
    
    sayColor.call(this);//red
    sayColor.call(window);//red
    sayColor.call(o);//blue
    

    30、ECMAScript5还定义了一个方法:bind()。这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

    window.color = "red";
    var o = {color:"blue"};
    
    function sayColor(){
      alert(this.color);
    }
    
    var objectSayColor = sayColor.bind(o);
    objectSayColor();//blue
    

    这些是看这本书的前六章的笔记,后面还会记录之后几章的笔记。买的尤克里里回来了,买的苹果电脑也到了,双十一什么也没买,但是依然要吃吐了,捂脸。。。

    要多看书,多写笔记,多敲代码,要不然都对不起这么贵的MacBook Pro....

    相关文章

      网友评论

        本文标题:javascript高级程序设计(第三版)读书书笔记(一)

        本文链接:https://www.haomeiwen.com/subject/puawmxtx.html