美文网首页
JavaScript学习笔记

JavaScript学习笔记

作者: junjunxx | 来源:发表于2017-09-01 17:08 被阅读12次

    1.JavaScript基本数据类型

    ​ number typeof -> number
    ​ boolean typeof -> boolean
    ​ string typeof -> string
    ​ undefined typeof -> undefined
    ​ null typeof -> object

    2.全局变量/局部变量

    ​ 全局变量:
    ​ 1.定义在函数外面的变量,称为全局变量;很少用
    ​ 2.定义在函数内部,没有使用var声明的变量,称为全局变量。

    ​ 局部变量:
    ​ 方法内部,用var声明的变量,称为局部变量。

    3.使用Array模拟栈结构

    var arr = [1, 2, 3];
    arr.push(true, false);  //push可以向数组尾部添加一个或者多个元素,返回新增元素后数组的长度
    arr.pop();             //从数组尾部移除一个元素,返回移除的元素 false                                  
    

    4.使用Array模拟队列结构

    var arr = [1, 2, 3];
    arr.push(true); //数组【1, 2, 3, true】
    arr.shift();    //从数组头部移除一个元素,返回移除元素 1  数组【2, 3, true】
    //unshift(1, 2); 向数组头部添加一个或者多个元素
    

    5.数组 splice/slice

    /**
    * splice
    *   第一个参数:起始位置
    *   第二个参数:截取的个数(没有此参数表示截除起始位置后面的所有元素)
    *   第三个参数及以后:追加的新元素(没有此参数表示截除起始位置后n(参数2的值)个元素)
    */
    var arr = [1, 2, 3, 4, 5];
    arr.splice(1, 2, 3, 4, 5);  
    console.log(arr);       //[1, 3, 4, 5, 4, 5]
    
    /**
    * slice,不操作数组本身
    *   第一个参数:起始位置
    *   第二个参数:结束位置(不包含结束的元素)
    */
    var arr = [1, 2, 3, 4, 5];
    var result = arr.slice(2, 4);
    console.log(arr);       //[1, 2, 3, 4, 5]
    console.log(result);    //[3, 4]
    

    6.数组 concat/join

    /**
    * concat,合并两个数组,生成一个新的数组,不操作数组本身
    */
    var arr1 = [1, 2, 3, 4, 5];
    var arr2 = [true, false]
    var result = arr1.concat(arr2); 
    console.log(arr1);      //[1, 2, 3, 4, 5]
    console.log(arr2);      //[true, false]
    console.log(result);    //[1, 2, 3, 4, 5, true, false]
    
    /**
    * join,用指定连接符链接数组所有元素,不操作数组本身
    *   第一个参数:起始位置
    *   第二个参数:结束位置(不包含结束的元素)
    */
    var arr1 = [1, 2, 3, 4, 5];
    var result = arr1.join("-");
    console.log(arr1);      //[1, 2, 3, 4, 5]
    console.log(result);    //1-2-3-4-5
    

    7.数组 sort/reverse

    var arr = [5, 2, 1, 4, 3];
    /**
    * sort,正序排列数组
    */
    arr.sort();
    console.log(arr);//[1, 2, 3, 4, 5]
    
    var arr1 = [10, 2, 4, 1, 7];
    arr1.sort();
    console.log(arr1);  //[1, 10, 2, 4, 7] 按照字符串来值比较
    //解决方案
    arr.sort(function (value1, value2) {
      if(value1 < value2){
        return -1;
      }else if(value1 > value2){
        return 1;
      }else{
        return 0
      }
    });
    
    
    /**
    * reverse,倒序排列数组,不是按照元素大小,而是按照元素索引倒序
    */
    arr.reverse();
    console.log(arr);   //[3, 4, 1, 2, 5]
    

    8.数组新特性-迭代(every/filter/forEach/map/some)

    every:对数组的每一个元素执行一次函数调用,都返回true,则返回true,若有一个返回false,则返回false

    var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    
    var result = arr.every(function (value, index, array) {
      return value > 2;
    });
    console.log(result);    //false
    

    filter:对数组的每一个元素执行一次函数调用,函数执行结果为false,则把该元素过滤掉,最后返回过滤后的结果

    var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    
    var result = arr.filter(function (value, index, array) {
      return value > 2;
    });
    console.log(result);    //[3, 4, 5, 4, 3]
    

    forEach:对数组的每一个元素执行一次函数调用,对每个元素进行操作,无返回

    var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    arr.forEach(function (value, index, array) {
      console.log(value);   //遍历输出数组的每一个元素
    })
    

    map:对数组的每一个元素执行一次函数调用,返回函数调用后的结果

    var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    var result = arr.map(function (value, index, array) {
      return value * 2;
    });
    console.log(result);    //[2, 4, 6, 8, 10, 8, 6, 4, 2]
    

    some:对数组的每一个元素执行一次函数调用,若有一个返回true,则返回true,如果都返回false,则返回false

    var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    var result = arr.some(function (value, index, array) {
      return value >= 5;
    });
    console.log(result);    //true
    

    reduce:从前往后遍历,preValue保留上一次函数运算的结果

    var arr = [1, 2, 3, 4, 5, 4, 3, 2, 1];
    var result = arr.reduce(function (preValue, curValue, index, array) {
      return preValue + curValue;
    });
    console.log(result);    //25 (1+2+3+4+5+4+3+2+1)
    

    reduceRight:与reduce相反,从后往前遍历

    9.Object基本方法

    ​ 每一个object对象都会有一下属性和方法

    ​ --Constructor:构造函数,保存着用于创建当前对象的函数;

    ​ --hasOwnProperty(propertyName):用于检测propertyName属性是否再当前实例中存在(不包括原型);

    ​ --isPrototypeOf(Object):检查传入的对象是否是另外一个对象的原型;

    ​ --propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for iny语句来枚举;

    ​ --toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应;

    ​ --toString():返回对象的字符串显示;

    ​ --valueOf():返回对象的字符串、数值、布尔显示;

    10.函数的3中定义方式

    //函数3中定义方式
    
    //1.function语句式,这种方法定义的函数会被提前提取编译
    function test1() {
      console.log("function语句式");
    }
    test1();        //function语句式
    
    //2.函数的直接量
    var test2 = function () {
      console.log("函数的直接量");
    }
    test2();        //函数的直接量
    
    //3.Function构造函数式,有动态性,拥有顶级作用于
    var test3 = new Function("a", "b", "console.log(a+b);");
    test3(10, 20);  //30
    
    //函数作用于概念
    var k = 1;
    function t1() {
      var k = 2;
      //function test() {return k;}             2
      //var test = function () {return k;};     2
      //var test = new Function("return k;");   1
      alert(test());
    }
    t1();
    

    11.function中的arguments

    ​ 每个function对象中都自带一个arguments对象,该对象存储了该function的实际参数列表,arguments是一个数组对象,通过 方法名.length 可以获取到方法申明的参数列表

    ​ arguments.callee 指向函数自己本身,类似递归的时候推荐使用,仔细看下面例子

    function fact(num) {
      if(num <= 1) {
        return 1;
      } else{
        return num * fact(num - 1);
      }
    }
    console.log(fact(5));   //120
    var F = fact;
    console.log(F(5));      //120
    fact = null;
    console.log(F(5));      //Uncaught TypeError:fact is not a function
    
    //标准定义
    function fact(num) {
      if(num <= 1) {
        return 1;
      } else{
        return num * arguments.callee(num - 1);
      }
    }
    

    12.this

    ​ this对象是再运行时基于函数的执行环境绑定的,在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。也就是说,this关键字总指向调用者。

    //this总是指向调用者
    var k = 10;
    function test() {
      this.k = 20;
    }
    console.log(test.k);    //undefined,因为test函数还未被调用
    test();                 //此处相当于window.test(),所以this指向的时window
    console.log(test.k);    //undefined
    console.log(k);         //20,相当于window.k
    

    13.call/apply

    ​ call/apply这两个方法是每一个function自带的成员方法,他们的作用一样,都是为function指定执行作用域,区别在于,call接受的参数是以参数列表的形式接受,而apple是将参数封装成数组进行接受的。

    var color = "red";
    var obj = {color:"blue"};
    
    function add(num1, num2) {
      console.log(this.color + ":" + (num1 + num2));
    }
    
    function call1(obj, num1, num2) {
      add.call(obj, num1, num2);
    }
    
    function apply1(obj, num1, num2) {
      add.apply(obj, [num1, num2]);
    }
    
    call1(this, 10, 20);        //red:30
    apply1(this, 20, 40);       //red:60
    
    call1(obj, 10, 20);         //blue:30
    apply1(obj, 20, 40);        //blue:60
    

    14.执行环境

    执行环境(execution context)是javascript中最为重要的一个概念。执行环境定义了变量或者函数有权访问的其他数据,决定了他们各自的行为。每一个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。

    15.作用域链

    ​ 每一个函数都有自己的执行环境,当执行流进一个函数时,韩式的环境就会被推入 一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返还给之前的执行环境。当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。

    16.块级作用域

    ​ JavaScript没有跨级作用于的概念,如下例

    function test() {        
      for(var i = 0; i <= 5; i++){
        console.log(i);
      }        
      console.log(i);       //6,此处依然能访问到i
    }
    test();
    

    ​ 我们可以通过()()的方式模拟块级作用域,

    function test() {
      (function () {
        for(var i = 0; i <= 5; i++){
          console.log(i);
        }
      })();
    
      console.log(i);   //Uncaught ReferenceError: i is not defined
    }
    

    17.闭包

    闭包;一个函数可以访问另外一个函数作用域中的变量,起到保护变量的作用
    

    ​ 自己理解:一个函数返回另一个函数,返回的函数有外部作用域的访问权限

    var name = "abc";
    var obj = {
      name : "efg",
      getName: function () {
        return function () {
          return this.name;
        }
      }
    };
    /**
    * 这个方法可以拆解理解的
    * var fun = obj.getName() = function(){return this.name}
    * fun() = window.fun()
    * 所以会返回外部作用于的name
    */
    console.log(obj.getName()());   //abc
    
    //返回obj.name解决方案
    var obj1 = {
      name:"efg",
      getName:function () {
        var o = this;
        return function () {
          return o.name;
        }
      }
    };
    console.log(obj1.getName()());  //efg
    

    18.面向对象

    18.1.创建面向对象的3种方式
    //1.普通方法调用
    function createPerson(name, age, sex) {
        var obj = {};
        obj.name = name;
        obj.age = age;
        obj.sex = sex;
        return obj;
    }
    var person = createPerson("zhangsan", 20, "男");
    console.log(person.name + ":" + person.age + ":" + person.sex);     //zhangsan:20:男
    
    //2.构造函数创建,这种方式,函数名都是首字母大写
    function Person(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    var person  = new Person("lisi", 25, "男");
    console.log(person.name + ":" + person.age + ":" + person.sex);     //lisi:25:男
    
    //3.通过call/apply的形式调用
    var person = {};
    Person.apply(person, ["wangwu", 30, "女"]);
    console.log(person.name + ":" + person.age + ":" + person.sex);     //wangwu:30:女
    
    18.2.原型(prototype)

    ​ 原型(prototype);每一个函数对象都有一个prototype属性,该属性是一个指针,指向一个对象,这个对象的用途是将特定的属性和方法封装起来,共实例对象共享使用。

    function Person() {}
    Person.prototype.name = "zhangsan";
    Person.prototype.age = 20;
    Person.prototype.sayName = function () {
      console.log(this.name);
    };
    
    var p1 = new Person();
    p1.name = "lisi";
    var p2 = new Person();
    p2.name = "wangwu";
    
    p1.sayName();       //lisi
    p2.sayName();       //wangwu
    console.log(p1.sayName == p2.sayName);      //true
    console.log(Person.prototype.isPrototypeOf(p1));    //true  判断是否是某对象的原型
    console.log(Object.getPrototypeOf(p1));     //返回Person.prototype对象
    

    ​ 构造函数,原型对象,实例对象三者的关系
    ​ 1.构造函数.prototype = 原型对象
    ​ 2.原型对象.constructor = 构造函数(模板)
    ​ 3.原型对象.isPrototypeOf(实例对象) 判断实例对象的原型是否是当前对象

    18.3.原型的使用
    18.3.1.简单原型模式

    该模式要遵循的原则式创建对象必须放在原型后面,否则创建的对象无法访问到原型内的属性或方法

    function Person() {}
    
    Person.prototype = {
      name:'z3',
      age:20,
      sayName:function () {
        console.log(this.name);
      }
    }
    
    //定义Person.prototype的构造函数为Person,使用这种方法指定构造函数,for-in的时候无法获取到constructor
    Object.defineProperty(Person.prototype, "constructor", {
      enumerable:false,
      value:Person
    })
    
    var p = new Person();
    p.sayName();        //z3
    console.log(Person.prototype.constructor);  //function Person(){}
    
    18.3.2.组合使用构造函数和原型模式

    ​ 由于上述方式所有属性/方法对所有对象都是共享的,有一个明显的缺点,当属性是应用数据类型时,A对象对这个数组进行了push操作,B对象去访问时得到的时A对象操作后的结果。通过组合使用构造函数和原型模式可以有效解决这个问题

    function Person(name, age, friends) {
      this.name = name;
      this.age = age;
      this.friends = friends;
    }
    
    Person.prototype = {
      constructor : Person,
      sayName : function () {
        console.log(this.name);
      }
    }
    
    var p1 = new Person('z1', 20, ["aaa", 'bbb']);
    p1.friends.push('zzz');
    var p2 = new Person('z2', 22, ['ccc', 'ddd']);
    p2.friends.push('yyyy');
    
    p1.sayName();           //z1
    p2.sayName();           //z2
    console.log(p1.friends);    //["aaa", "bbb", "zzz"]
    console.log(p2.friends);    //["ccc", "ddd", "yyyy"]
    
    18.3.3.动态原型模式

    ​ 该模式把所有的属性和方法封装到一起,代码更加简洁,如下方式定义,sayName只会被创建一次

    function Person(name, age) {
      this.name = name;
      this.age = age;
    
      if(typeof this.sayName != "function"){
        Person.prototype.sayName = function () {
          console.log(this.name);
        }
      }
    }
    
    var p1 = new Person('z1', 20);
    var p2 = new Person('z3', 22);
    p1.sayName();       //z1
    p2.sayName();       //z3
    
    18.3.4.稳妥构造函数式

    ​ 适合在非常安全的环境中使用,他没有公共属性,不能使用this对象,同时创建的时候也不使用new,这种方法类似与java中的private,所有属性都无法通过obj.xxx的方式获取,必须通过对应的方法获取。

    function Person() {
      var obj = {};
      var name = 'z1';
      var age = 20;
      obj.sayName = function () {
        console.log(name);
      }
      return obj;
    }
    
    var p = Person();
    p.sayName();        //z1
    

    19.继承

    ​ JavaScript通过让子类对象的原型指向父类对象的方式实现继承

    19.1.原型继承

    ​ 特点:即继承了父类的模板,又继承了原型对象

    function Sup(name){
      this.name = name;
    }
    function Sub(age) {
      this.age = age;
    }
    
    var sup = new Sup('z3');
    Sub.prototype = sup;
    
    var sub = new Sub(20);
    console.log(sub.name);                  //z3
    console.log(sub.age);                   //20
    console.log(sup.isPrototypeOf(sub));    //true
    console.log(Sub.prototype.constructor); //function Sup(name){this.name = name;}
    console.log(sub instanceof Sub);        //true
    console.log(sub instanceof Sup);        //true
    
    19.2类继承

    ​ 特点:只继承模板,不继承原型对象,又称借用构造函数方式继承

     function Person(name, age) {
       this.name = name;
       this.age = age;
     }
    
    function Boy(name, age, sex) {
      Person.call(this, name, age);
      this.sex = sex;
    }
    
    var boy = new Boy('z3', 20, '男');
    console.log(boy.name + " : " + boy.age + " : " + boy.sex);  //z3 : 20 : 男
    console.log(boy instanceof Boy);        //true
    console.log(boy instanceof Person);     //false
    console.log(Boy.prototype.constructor); //Boy(name, age, sex) {Person.call(this, name, age);this.sex = sex;}
    
    19.3混合继承
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    
    function Boy(name, age, sex) {
      Person.call(this, name, age);
      this.sex = sex;
    }
    
    Boy.prototype = new Person();
    
    var boy = new Boy('z3', 20, '男');
    console.log(boy.name + " : " + boy.age + " : " + boy.sex);  //z3 : 20 : 男
    console.log(boy instanceof Boy);        //true
    console.log(boy instanceof Person);     //true
    console.log(Boy.prototype.constructor); //Person(name, age) {this.name = name;this.age = age; }
    
    20.Ajax
    20.1创建XHR

    目前Javascript主流的都是通过Ajax技术进行网络请求的,Ajax可以不需要刷新页面的同时与服务器进行交互,提高用户体验,Ajax的核心是XMLHttpRequest,目前主流的浏览器都支持原生的XHR,但是IE7以前使用的是MSXML库中的XHR对象,所以为了兼容性,我们可以通过一下方式获取XHR

    function createXHR() {
      if(typeof XMLHttpRequest != "undefined"){
        return new XMLHttpRequest();
      }else if(typeof ActiveXObject != "undefined"){
        if(typeof arguments.callee.activeXString != "string"){
          var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];
          var i, len;
          for(i = 0, len = versions.length; i < len; i++){
            try{
              new ActiveXObject(versions[i]);
              arguments.callee.activeXString = versions[i];
              break;
            }catch (ex){
    
            }
          }
        }
        return new ActiveXObject(arguments.callee.activeXString);
      }else{
        throw new Error("No XHR object available");
      }
    }
    
    20.2同步请求
    var xhr = createXHR();
    xhr.open("get",
             "https://accountv3-api.fclassroom.cn/checkVersion.json?jike-client-from=APP&versionType=21&category=20&versionNo=356",
             false);
    
    xhr.send(null);
    if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
      console.log(xhr.responseText);
    }else{
      console.log("Request was unsuccessful : " + xhr.status);
    }
    

    20.3异步请求

    var xhr = createXHR();
    xhr.onreadystatechange = function () {
      /**
      * readyState
      * 0:未初始化
      * 1:启动
      * 2:发送
      * 3:接收
      * 4:完成
      */
      if(xhr.readyState == 4){
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
          console.log(xhr.responseText);
        }else{
          console.log("Request was unsuccessful : " + xhr.status);
        }
      }
    }
    xhr.open("get",
             "https://accountv3-api.fclassroom.cn/checkVersion.json?jike-client-from=APP&versionType=21&category=20&versionNo=356",
             true);
    xhr.send(null);
    

    20.4Get/Post

    get请求与上述方式一样,如果需要为请求添加自己的header,可以通过XHR的setRequestHeader(name,value)进行设置,这个方法的调用必须在open之后,send之前。

    post请求可以通过FormData来承载需要提交的数据

    var xhr = createXHR();
    xhr.onreadystatechange = function () {
      if(xhr.readyState == 4){
        if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
          console.log(xhr.responseText);
        }else{
          console.log("Request was unsuccessful : " + xhr.status);
        }
      }
    }
    xhr.open("post",
             "https://accountv3-api.fclassroom.cn/checkVersion.json",
             true);
    var formData = new FormData();
    formData.append("jike-client-from", "APP");
    formData.append("versionType", "21");
    formData.append("category", "20");
    formData.append("versionNo", "356");
    xhr.send(formData);
    

    相关文章

      网友评论

          本文标题:JavaScript学习笔记

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