前端小白学JavaScript

本文深入探讨JavaScript的基础知识,包括数据类型、对象创建、属性操作及构造函数。重点讲解对象的概念,如何通过构造函数创建对象,以及原型链、继承的各种方式。同时,介绍了闭包及其在变量作用域和内存管理中的作用,最后提到了ES6的重要特性。
摘要由CSDN通过智能技术生成

JavaScript基本知识

  • JS的用途:Javascript可以实现浏览器端、服务器端(nodejs)。。。
  • 浏览器端JS由以下三个部分组成:
    • ECMAScript:基础语法(数据类型、运算符、函数。。。)
    • BOM(浏览器对象模型):window、location、history、navigator。。。
    • DOM(文档对象模型):div、p、span。。。
  • ECMAScript又名es,有以下重大版本:
    • 旧时代:
      • es1.0。。。es3.1
    • 新时代:
      • es5
      • es6(es2015)
      • es7(es2016)、es8(es2017)

数据类型

  • 基本数据类型——值类型:(数字、字符串、布尔值、null、undefined)
    • undefined类型?
  • 复杂数据类型——引用类型:(对象)
    • 数组
    • 函数
    • 正则表达式
    • Date

对象的基本使用

创建一个对象

    var student={ 
        name:"李白" , //student有一个name属性,值为"李白"
        grade:"初一" ,
        //a、student有一个say属性,值为一个函数
        //b、student有一个say方法
        say:function(){
            console.log("你好");
        },
        run:function(speed){
            console.log("正在以"+speed+"米/秒的速度奔跑");
        }
    }

对象是键值对的集合:对象是由属性和方法构成的 (ps:也有说法为:对象里面皆属性,认为方法也是一个属性)

  • name是属性 grade是属性
  • say是方法 run是方法
  • –键:指对象的属性(方法)
  • –值:指对象属性(方法)的值

对象属性操作

获取属性:

第一种方式:.语法

  • student.name 获取到name属性的值,为:“李白”
  • student.say 获取到一个函数

第二种方式:[]语法

号外:2种方式的差异:

  • .语法更方便,但是坑比较多(有局限性),比如:

    • .后面不能使用js中的关键字、保留字(class、this、function。。。)

    • .后面不能使用数字

      var obj={};
      obj.this=5; //语法错误
      obj.0=10;   //语法错误
      
  • []使用更广泛

    • o1[变量name]
    • [“class”]、[“this”]都可以随意使用 obj[“this”]=10
    • [0]、[1]、[2]也可以使用
      • obj[3]=50 = obj[“3”]=50
      • 思考:为什么obj[3]=obj[“3”]
    • 甚至还可以这样用:["[object Array]"]
      • jquery里面就有这样的实现
    • 也可以这样用:["{abc}"]
      • 给对象添加了{abc}属性

设置属性

  • student[“gender”]=“男” 等价于: student.gender=“男”

    • 含义:如果student对象中没有gender属性,就添加一个gender属性,值为"男"
    • 如果student对象中有gender属性,就修改gender属性的值为"男"
  • 案例1:student.isFemale=true

  • 案例2:student[“children”]=[1,2,5]

  • 案例3:

      student.toShanghai=function(){   
          console.log("正在去往上海的路上")   
      }
    

删除属性

  • delete student[“gender”]
  • delete student.gender

通过构造函数创建对象

构造函数创建对象的例子:

  • var xiaoming = new Object() --> var xiaoming = {};
  • var now = new Date()
  • var rooms = new Array(1,3,5) --> var rooms = [1,3,5]
  • var isMale=/123/; ==> var isMale=new RegExp(“123”)
    • isMale是通过RegExp构造函数创建出来的对象
    • isMale是RegExp构造函数的实例
  • 以上例子中,Object、Date、Array都是内置的构造函数

自定义一个构造函数来创建对象

  • 构造函数

      function Person(name,age){
          this.name=name;
          this.age=age;
      }
      var p1=new Person("赵云",18)
    
  • 说明:p1就是根据【Person构造函数】创建出来的对象

构造函数的概念

  • 任何函数都可以当成构造函数
    function CreateFunc(){ }
  • 只要把一个函数通过new的方式来进行调用,我们就把这一次函数的调用方式称之为:构造函数的调用
    • new CreateFunc(); 此时CreateFunc就是一个构造函数
    • CreateFunc(); 此时的CreateFunc并不是构造函数

关于new Object()

  • new Object()等同于对象字面量{}

构造函数的执行过程

var p1=new Person();

  • 1、创建一个对象 (我们把这个对象称之为Person构造函数的实例)- _p1
  • 2、创建一个内部对象,this,将this指向该实例(_p1)
  • 3、执行函数内部的代码,其中,操作this的部分就是操作了该实例(_p1)
  • 4、返回值:
    • a、如果函数没有返回值(没有return语句),那么就会返回构造函数的实例(p1)

    • b、如果函数返回了一个基本数据类型的值,那么本次构造函数的返回值是该实例(_p1)
      function fn(){

        }
        var f1=new fn();    //f1就是fn的实例
      
        function fn2(){
            return "abc";
        }
        var f2=new fn2();   //f2是fn2构造函数的实例
      
    • c、如果函数返回了一个复杂数据类型的值,那么本次函数的返回值就是该值
      function fn3(){
      return [1,3,5];
      //数组是一个对象类型的值,
      //所以数组是一个复杂数据类型的值
      //–>本次构造函数的真正返回值就是该数组
      //–>不再是fn3构造函数的实例
      }
      var f3=new fn3(); //f3还是fn3的实例吗?错
      //f3值为[1,3,5]

继承

JS中继承的概念:

  • 通过【某种方式】让一个对象可以访问到另一个对象中的属性和方法,我们把这种方式称之为继承 并不是所谓的xxx extends yyy

为什么要使用继承?

  • 有些对象会有方法(动作、行为),而这些方法都是函数,如果把这些方法和函数都放在构造函数中声明就会导致内存的浪费

      function Person(){
          this.say=function(){
              console.log("你好")
          }
      }
      var p1=new Person();
      var p2=new Person();
      console.log(p1.say === p2.say);   //false
    

继承的第一种方式:原型链继承1

    Person.prototype.say=function(){
        console.log("你好")
    }
  • 缺点:添加1、2个方法无所谓,但是如果方法很多会导致过多的代码冗余

继承的第二种方式:原型链继承2

    Person.prototype={
        constructor:Person,
        say:function(){
            console.log("你好");
        },
        run:function(){
            console.log("正在进行百米冲刺");
        }
    }
  • 注意点:
  • a、一般情况下,应该先改变原型对象,再创建对象
  • b、一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构

继承的第三种方式:拷贝继承(混入继承)

  • 场景:有时候想使用某个对象中的属性,但是又不能直接修改它,于是就可以创建一个该对象的拷贝

  • 实现1:

      var source={name:"李白",age:15}
      var target={};
      target.name=source.name
      target.age=source.age;
    
  • 上面的方式很明显无法重用,实际代码编写过程中,很多时候都会使用拷贝继承的方式,所以为了重用,可以编写一个函数把他们封装起来:

      function extend(target,source){
          for(key in source){
              target[key]=source[key];
          }
          return target;
      }
      extend(target,source)
    
  • 由于拷贝继承在实际开发中使用场景非常多,所以很多库都对此有了实现

    • jquery:$.extend
  • es6中有了对象扩展运算符仿佛就是专门为了拷贝继承而生:

      var source={name:"李白",age:15}
      var target={ ...source }
    

继承的第四种方式:原型式继承

  • 场景:
    • 创建一个纯洁的对象
    • 创建一个继承自某个父对象的子对象
  • 使用方式:
    • 空对象:Object.create(null)
    •   var o1={ say:function(){} }
        var o2=Object.create(o1);
      

继承的第五种方式:借用构造函数实现继承

  • 场景:适用于2种构造函数之间逻辑有相似的情况

function Animal(name){

this.name=name;

}

function Person(name,age){

this.name=name;

this.age=age;

}

  • 以上代码用借用构造函数实现

    function Animal(name,age){
    this.name=name;
    this.age=age;
    }
    function Person(name,age,address){
    Animal.call(this,name);
    //this.name=name;
    //this.age=age;
    this.address=address;
    }

原型链

闭包

变量作用域

  • 变量作用域的概念:就是一个变量可以使用的范围
  • JS中首先有一个最外层的作用域:称之为全局作用域
  • JS中还可以通过函数创建出一个独立的作用域,其中函数可以嵌套,所以作用域也可以嵌套

作用域链

  • 由于作用域是相对于变量而言的,而如果存在多级作用域,这个变量又来自于哪里?这个问题就需要好好地探究一下了,我们把这个变量的查找过程称之为变量的作用域链

  • 简单来说,作用域链可以用以下几句话来概括:(或者说:确定一个变量来自于哪个作用域)

    • 查看当前作用域,如果当前作用域声明了这个变量,就确定结果
      • 查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声明
        • 再查找上级函数的上级函数,直到全局作用域为止
          • 如果全局作用域中也没有,我们就认为这个变量未声明(xxx is not defined)
  • 举例1:

      var name="张三";
      function f1(){
          var name="abc";
          console.log(name);
      }
      f1();
    
  • 举例2:

      var name="张三";
      function f1(){
          console.log(name);
          var name="abc";
      }
      f1();
    
  • 举例3:

      var name="张三";
      function f1(){
          console.log(name);
          var name="abc";
      }
      f1();
    
  • 举例4:

      var name="张三";
      function f1(){
          return function(){
              console.log(name);
          }
          var name="abc";
      }
      var fn=f1();
      fn();
    
  • 举例5:

      var name="张三";
      function f1(){
          return {
              say:function(){
                  console.log(name);
                  var name="abc";
              }
          }
      }
      var fn=f1();
    

闭包的问题

    function fn(){
        var a=5;
        return function(){
            a++;
            console.log(a);
        }
    }
    var f1=fn();
    f1();
    f1();
    f1();

闭包问题的产生原因

  • 函数执行完毕后,作用域中保留了最新的a变量的值

闭包的应用场景

  • 模块化
  • 防止变量被破坏

es6内容

需要理解的内容:

  • 1、解构赋值
  • 2、函数rest参数
  • 3、箭头函数
    • 箭头函数和普通函数有哪些不同?(4点)
  • 4、对象的Object.assign
  • 5、promise
  • 6、generator
  • 7、async
  • 8、class
  • 9、module
    es6学习推荐网站
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值