美文网首页
JavaScript 基础

JavaScript 基础

作者: Gu1yun_张 | 来源:发表于2018-10-06 23:49 被阅读0次

    浏览器

    1. 主流浏览器

      • IE Trident
      • Firefox Gecko
      • Safari Webkit
      • Chrome Webkit/Blink
      • Opera Presto
    2. 浏览器组成部分

      1. shell 部分
      2. 内核部分
        • 渲染引擎(语法规则和渲染)
        • js 引擎
        • 其他模块

    JavaScript基础知识

    引入方式
    1. 内部脚本

    2. 外链脚本

    WEB标准

    W3C标准:结构、样式、行为相分离,通常都会采用外链的方式

    变量(varible)
    • 变量声明

      • 声明、赋值分解

        var a; //变量声明
        a = 1000;  //变量赋值
        
      • 单一 var

        var a, 
            b, 
            c = 300, 
            d = 400, 
            e = 500;
        a = 100;
        b = 200;
        //...
        
    • 命名规则

      1. 变量名必须以 英文字母 、_ 、$ 开头
      2. 变量名可以包括 英文字母、_ 、$、数字
      3. 不可以使用系统的 关键字、保留字 作为变量名
    值类型 - 数据类型
    1. 原始值
      • Number 数值类型
      • String 字符串类型
      • Boolean 布尔类型
      • Undefined 使用的变量定义后未赋值
      • Null 空值,对象占位符
    2. 引用值
      • Array 数组类型
      • Object 对象
      • Function 函数
      • Date 时间函数
      • RegExp 正则表达式
    3. 两种值得区别
      1. 原始值存储于栈(stack)内存中 先进后出(first in last out)

      2. 引用值大部分存储于堆(heap)内存中 (先进先出)

    Error
    1. 语法错误

    2. 逻辑错误

    3. 一个代码块发生错误,不会影响其他代码块的执行

    运算操作符
    • “ + ”

      1. 数学运算、字符串连接
      2. 任何数据类型与字符串相加都等于字符串
    • “ - “,” * “,” / “," % ",” = “,” () “

      1. 与数学运算相同
      2. ” () “ 优先级最高,” = “ 优先级最低
    • ” ++ “,” -- “,” += “,” -= “,” /= “,” *= “,” %= “

    比较运算符
    • ” > “,” < “,” == “,” >= “,” <= “,” != “

    • 比较的结果为 boolean 类型

    • 字符串比较的是 ascii 码

    逻辑运算符
    • ” && “,” || “,” ! “

      • data && console.log('数据传递失败');       //短路语句
        
      • var a = 0 || false || 1;
        var handleClick = function(e) {
            var event = e || window.event;   // 做IE浏览器的兼容
        }
        
    • 被认为 false 的值

      • undefined

      • null

      • NaN

      • ""

      • 0

      • false

    条件语句
    • if

    • if else

    • while

    • do-while

    • switch case

    • break

    • continue

    typeof 六种数据类型
    • number

    • string

    • boolean

    • object

      • 数据、对象和null都会返回object (null 最初是对象占位符,属于历史遗留问题)
    • undefined

    • function

    类型换换
    • 显示类型转换

      • Number(num); 将其参数转换为数值类型并返回。 null = 0, undefined = NaN, "123abc" = NaN
      • parseInt(num,基底); 将第一个参数转换为整数类型并返回,第二个参数可以表明第一个参数的基底,然后转换为十进制,进行到非数字位截止。 true/false = NaN, 123.9 = 123 , 123abc = 123
      • parseFloat(num); 转换成浮点类型,识别到非数字位并且只识别一个小数点
      • String(str); 转换为字符串
      • Boolean(); 转换为布尔类型
      • toString(redix); 是用 “.” 的方式调用当前方法,转换成字符串类型, radix 转换成目标进制。 undefined / null 不可以使用当前方法
    • 隐式类型转换

      • isNaN(); 判断是不是不是一个数

        isNaN('abc') -隐式调用-> Number('abc') =然后和NaN进行比较= NaN?  true:false;
        
        
      • ++/-- 、+/-(一元正负)

        //自动隐式调用Number(),强制转换成Number类型
        var a = "123";
        a++;
        // a = 124
        var b = "abc";
        b++;
        // b = NaN
        

        当加号两边有一个是字符串的,则将两边都转换为字符串并连接,如果是数值就做加法运算

      • -、*、/、%

        隐式调用Number()方法,

      • &&、||、!

      • <、>、<=、>=

        比较时数字优先

      • ==、!=

        数值类型

    • 不发生类型转换

      • ===
      • !==
    函数
    • 定义

      • 函数声明

        function function_name() {
        }
        
      • 函数表达式

        // 命名函数表达式
        var function_name = function test() {  
            // test不代表函数体,在函数中 function_name.name  == test 
            console.log(function_name.name);   //test
        }
        // 匿名函数表达式 ** 常用 推荐 **
        var function_name = function() {
            
        }
        
    • 组成形式

      • 函数名称

        • 命名规则和变量一致
        • 多个单词使用小驼峰命名法 theIsFunctionName
      • 参数

        • 形参

          // 传递形式参数(形参)
          function function_name(a, b) {
              // 在括号中传递a, b就相当于 隐式的在函数中  var a; var b;
          }
          
        • 实参

          // 传递实际参数(实参)
          function_name(1, 2);
          
        • arguments 实参列表

          一个类数组,保存传进来的实参

          function function_name(a, b, c) {
              console.log(arguments);   // 打印实参列表
              console.log(function_name.length);  // 计算形参的长度
          }
          function_name(1, 2, 4)
          
      • return

        • 终止函数

          return 之后的语句将不会得到执行

        • 返回值

          将内部值返回到外部

    递归
    • // 1. 找规律    2. 找出口
      
      // 使用递归实现阶乘和斐波那契数列
      function mul(n) {
          if(n == 1 || n == 0) {
              return 1;
          }
          return n * mul(n - 1);
      }
      console.log(mul(5))
      
      function fb(n) {
          if(n == 1 || n == 2) {
              return 1;
          }
          return fb(n-1) + fb(n-2);
      }
      fb(10);
      
    JS执行三部曲(预编译)
    1. 语法分析(通篇扫描是否存在语法错误)

    2. 预编译

      预编译发生在函数执行的前一刻

      函数声明整体提升,变量 声明提升,提升到逻辑的最前

      不够严谨

      • 预编译前奏

        1. imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为全局对象所有。

          a =  123;   // a 为全局变量
          function ao() {
              var a = b = 123;   // b 为暗示全局变量 
          }
          
        2. 一切声明的全局变量,全是window的属性。

          <script>
              var a  = 123;   // === window.a = 123;
              b = 234;    // === window.b = 234;
          </script>
          
      • 预编译四部曲

        1. 创建AO()对象
        2. 将形参和变量声明作为AO对象的属性,并赋值undefined
        3. 将实参和形参相统一
        4. 将函数声明作为AO对象的属性,并将函数体作为它的的值
        function fn(a) {
            console.log(a);    // fn() {}
            var a = 123;
            console.log(a);    // 123
            function a() {};
            console.log(a);    // 123
            var b = function() {};
            console.log(b);    // fn() {}
            function d() {};
        }
        fn(1);
        
        /*
           1.创建AO对象
            AO{
            
            }
            
            2.将形参和变量声明作为AO对象的属性,并赋值 undefined
            AO{
               a : undefined   形参和变量相同时后者覆盖
               b : undefined
            }
            
            3.将实参和形参相统一
            AO{
               a : 1,
               b : undefined
            }
            
            4.将函数声明作为AO对象的属性,并赋值函数体
            AO{
               a : fn(){}
               b : undefined
               d : fn(){}
            }
        */
        
    3. 解释执行

    作用域
    1. 作用域初探

      作用域定义:变量(变量作用域又称上下文)和函数生效(能被访问)的区域

      • 全局变量

        <script>
           var a = 10; // 全局变量    
        </script>
        
      • 局部变量

        <script>
            function test() {
               var b = 20;   // 局部变量
           }    
        </script>
        
      • 访问顺序

        内部可以访问外部变量,外部不可以访问内部变量,自内向外

    2. 作用域精解

      • 执行期上下文

        当函数执行时,会创建一个称为 执行期上下文 的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行期上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行期上下文,当函数执行完毕,它所产生的执行期上下文被销毁

      • 查找变量

        从作用域的顶端依次向下查找

      • [[ scope ]]

        每个javascript函数都是一个对象,对象中有些属性我们可以访问(例如: function_name.name),但有些不可以,这些属性仅供javascript引擎存取,[[ scope ]] 就是其中一个。

        [[ scope ]] 指的就是我们所说的作用域,其中存储了执行期上下文的集合。

      • 作用域链

        [[ scope ]] 中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链

      // 每个函数被创建时,会根据当前的执行环境生成作用域链,保存在当前函数的 [[ scope ]] 属性作用域链中
      // 当函数被执行时,会生成自己的作用域放在[[ scope ]]属性作用域链的最顶端
      
      function a() {      // 1. a 函数被定义  [[ scope ]]  0 : GO
          function b() {   // 3. b 函数被定义,拿到当前执行环境的作用域链 [[ scope ]] 0 : AO(a 函                          数的AO), 1 : GO
              var b = 234;
          }
          var a = 123;
          b();         // 4. b 函数被执行,生成自己的执行期上下文(AO对象),存进 [[ scope ]]作                         用域链中  0 : AO(b 函数的), 1 : AO(a 函数的), 2 : GO
      }
      var glob = 100;
      a();  // 2. a 函数 被执行 [[ scope ]] 0 : AO(a 函数的AO对象), 1 : GO
      
    3. 总结案例

      function a() {
          function b() {
              function c() {
                  
              }
              c();
          }
           b();
      }
      a();
      // a defined a.[[ scope ]] --> 0 : GO
      
      // a doing   a.[[ scope ]] --> 0 : aAO
      //                             1 : GO
      
      // a 的执行,产生了 b 的定义
      
      // b defined b.[[ scope ]] --> 0 : aAO
      //                             1 : GO
      
      // b doing   b.[[ scope ]] --> 0 : bAO
      //                             1 : aAO
      //                             2 : GO
      
      // b 的执行,产生了 c 的定义
      
      // c defined c.[[ scope ]] --> 0 : bAO
      //                             1 : aAO
      //                             2 : GO
      
      // c defined c.[[ scope ]] --> 0 : cAO
      //                             1 : bAO
      //                             2 : aAO
      //                             3 : GO
      
      // 所有的 GO、aAO、bAO、cAO 都是同一个执行上下文
      // 当一个函数执行完毕时,相对应的执行上下文也会跟着销毁
      
      
    闭包
    • 定义

      当内部函数被保存到外部时,将生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏。

    • 作用

      • 实现公有变量(累加器)

        function add() {
            var count = 0;
            function demo() {
                count ++;
                console.log(count);
            }
            return demo;
        }
        var counter = add();
        counter();
        counter();
        counter();
        
      • 做缓存(存储结构)

        function test() {
            var num = 100;
            function a() {
                num ++;
            }
            function b() {
                num --;
            }
            return [a, b];
        }
        var myArr = test();
        myArr[0]();
        myArr[1]();
        
        // -----------------------------------------------------------------------------
        
        function eater() {
            var food = "";
            var obj = {
                eat : function(){
                    console.log("i am eating" + food);
                },
                push : function(myFood) {
                    food = myFood;
                }
            }
            return obj;
        }
        obj.eat();
        
      • 实现封装,属性私有化

        
        
        
      • 模块化开发,防止污染全局变量

    • 案例

      function a() {
          var num = 100;
          function b() {
              num ++;
              console.log(num);
          }
          return b;  // 将 b 返回到外部,导致原有的作用域链不释放
      }
      var demo = a();
      demo();    //101
      demo();    //102
      
    立即执行函数
    • 定义

      此类函数没有声明,在一次执行过后释放。适合初始化工作

    • 语法

      // 立即执行函数执执行完之后立即销毁,初次之外和普通函数没有任何不同
      var num = (function (a, b, c) {
          
          return a + b + c;
          
      }(1, 2, 3))
      
    • 拓展

      // 立即函数不同写法
      (function () {}());  // W3C推荐
      (function () {})(); 
      
      // 只有表达式才可以被执行符号执行
      
      function test() {
          console.log('a');
      }();  // 语法错误,此种方式不可以被执行,这种叫做函数声明
      
      // 能被执行符号执行的函数,这个函数的名字就会被自动忽略
      
      var a = function() {  // a 不再代表函数了
          console.log('a');
      }();  // 可以,函数表达式
      
      // ()、+(正)、-(负)、!、&&、|| 都可以将一个函数转换为表达式
      
      - function() {
          console.log('a');
      }();
      // ...
      
      // !!! 注意
      function test(a, b, c) {  // 在这中情况下,系统不会报错,但也不会执行
          console.log(a, b, c)
      }(1, 2, 3);
      // 系统会自动识别成这样
      function test(a, b, c) {
          console.log(a, b, c);
      }
      (1, 2, 3); // 不识别成执行符号,看做一个独立的**逗号表达式(知识点再后续文档中呈现)**
      
      
    闭包补充
    1. 闭包的防范

      闭包会导致多个执行函数共用一个公有变量,如果不是特殊需求,尽量防止这种情况发生。

    2. 经典案例

      // 给数组的每一位绑定一个函数,并打印出当前下标
      function test() {
          var arr = [];
          for(var i = 0; i < 10; i ++) {
              arr[i] = function () {      // 赋值函数
                  document.write(i + " ")
              }
          }
          return arr;  // 返回到外部,形成了闭包
      }
      var myArr = test();
      for(var j = 0; j < 10; j ++) {
          myArr[j]();
      }
      // 执行结果 10 10 10 10 10 10 10 10 10 10    
      // 形成了闭包,由于在执行数组中的函数时,test 已经执行完毕。 i = 10并不再循环,这是for的判断条件
      // 形成闭包执行,这10个函数访问的 i 在 test的AO里都已经变成了10
      
      // 解决方法
      function test() {
          var arr = [];
          for(var i = 0; i < 10; i ++) {
              (function(n) {    // 使用立即执行函数
                  arr[n] = function() {
                      document.write(n + " ")
                  }
              }(i))
          }
          return arr;
      }
      var myArr = test();
      for(var j = 0; j < 10; j ++) {
          myArr[j]();
      }
      
    逗号操作符
    // 逐个审查每一位元素。如果某位元素需要计算,则计算该元素。最后,返回最后一个元素的计算结果
    var a = (2, 3);
    var f = (
        function f() {
            return '1';
        },
        function g() {
            return 2;
        }
    )();
    typeof(f);
    
    对象
    1. 是一种基础的变量类型,属于引用值

      var mrZhang = {
          name : 'zs',
          age : 22,
          sex : 'male',
          health : 100,
          smoke : function() {
              console.log('I am somkeing');
              mrZhang.health --; // this.health  this表示当前,第一人称
          }
      }
      
    2. 属性的增、删、改、查

      • mrZhang.wife = 'xiaoliu'
        
      • delete mrZhang.wife
        
      • mrZhang.sex = 'female'
        
      • mrZhang.name
        
    3. 对象的创建方法

      • 字面量

        var obj = {};    // plainObject 对象字面量 / 对象直接量
        
      • 构造函数

        • 系统自带

          new Object();  // 得出相同,且相互独立的对象
          Array();
          Number();
          Boolean();
          string();
          Date();
          
        • 自定义

          function Car(color) { // 为区分自定义函数,使用大驼峰命名法
              this.color = color;
              this.name = 'BMW';
              this.height = '1400';
              this.lang = '4900';
              this.weight = '1000';
              this.health = 100;
              this.run = function() {
                  this.health --;
              }
          }
          var car1 = new Car('red');
          var car2 = new Car('green')
          
          
      • 构造函数的内部原理

        // new 之后函数的变化
        function Student(name, age, sex) {
            // var this = {}, AO{ this:{name:'zhagnsan'} }  // 隐式创建一个this对象
            this.name = name;
            this.age = age;
            this.sex = sex;
            this.grade = 2017;
            
            // return this;  隐式 return this;
        }
        var student = new Student('zhangsan', 22, 'male');
        
        //------------------------------------------------------------------------------
        /*
           1. 在函数体最前面隐式的创建 this = {};
           2. 执行 this = xxx;
           3. 隐式的 return this;
               3.1. 可以手动显示 return ({}, [], /..)类型为obj的值,原始值是无效,自动忽略的
           
           !!!并不是最终形式,后续补充
        */
        
        // 模拟构造函数(只是简单模拟,并不推荐使用。因为还有更深层次的东西模拟不了,后续补充)
        function Person(name, height) {
            var that = {};
            that.name = name;
            this.height = height;
            return that; 
        }
        var person1 = Person('xiaowang', 180);
        
    包装类
    • Number();

    • String();

    • Boolean();

      // 包装类过程
      
      var num = 4;   
      // 原始值是坚决不能用属性的
      
      num.len = 3;   
      // new Number(4).len = 3;   
      // delete
      
      console.log(num.len)
      // new Number(4).len   undefined
      
    原型
    1. 定义:原型式 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承原型的属性和方法,原型也是对象。

      // Person.prototype  -- 原型
      // Person.prototype = {} 祖先
      Person.prototype.name = 'hehe';
      function Person() {
          // this.name = 'zs';  如何构造函数中存在和原型中相同的属性,会调用构造中的
      }
      var person1 = new Person(); // 都继承了原型的 name 属性
      var person2 = new Person();
      
      // 原型的 增、删、改、查
      // Person.prototype.sex = 'male'
      // delete Person.prototype.sex
      // Person.prototype.sex = 'female';  
      // Person.prototype.sex = 'male'
       
      Person.prototype = {   // 也可以这样定义原型
          height : 180,
          //...
      }
      
    1. 利用原型的特点和概念,可以提取共有属性。

      Car.prototype = {   // 将公有部分提取到原型中
          naem : 'BMW',
          height : 1400
          //...
      }
      function Car(color) {
          this.color = color;
      }
      var car1 = new Car('red');
      
    1. 对象如何查看对象的构造函数 -> constructor

      function Car() {
          
      }
      var car1 = new Car();
      console.log(car1.constructor); // 这个方法也是在原型中继承过来的,可以手动更改
      /*
      Car.prototype
       {constructor: ƒ}
           constructor: ƒ Car() 
           __proto__: Object 
      */
      
    2. 对象如何查看原型 -> 隐式属性 __proto__

      //  查看 person1.__proto__
      Person.prototype.name = 'zs';
      function Person() {
          // var this = {
          //    __proto__ : Person.prototype, 当发生 new 的时候,this对象中就会存在__proto__属性
          //                                 也就是说,如果 person1 查找属性,在Person构造中不                                         存在的话,就会通过__proto__属性所绑定的原型来查找,                                        这是系统提供的属性
          // }
      }
      var person1 = new Person(); 
      console.log(person1.name)
      
    原型链
    • 如何构成原型链?

      // 手动的更改构造函数的原型,连成一个链,称为原型链
      function Grand() {
          this.grandName = 'grand'
      }
      var grand = new Grand();
      
      Father.prototype = grand;
      function Father() {
          this.fatherName = 'father';
      }
      var father = new Father();
      
      Son.prototype = father;
      function Son() {
          this.sonName = 'son';
      }
      var son = new Son();
      
    • 原型链上属性的增删改查

      增删改当前属性只能使用当前属性的原型来操作

      
      
    • 绝大多数对象最终都会继承自 Object.prototype

      // 执行
      Object.create()
      
      // 错误信息
      VM100:1 Uncaught TypeError: Object prototype may only be an Object or null: undefined
          at Function.create (<anonymous>)
          at <anonymous>:1:8
                              
      Object.create(null);  // 创建出的对象不会继承自 Object.prototype
      
    • Object.create()

      // 创建一个对象并指定原型
      // var obj = object.create(原型)
      
      var obj = {name : 'zs', age : 22, sex : 'male'};
      var student = Object.create(obj);
      
      Person.prototype.name = 'ls';
      function Person() {
      }
      var obj1 = Object.create(Person.prototype);
      

    相关文章

      网友评论

          本文标题:JavaScript 基础

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