美文网首页
JS - 高级

JS - 高级

作者: Ht_何甜 | 来源:发表于2018-08-13 18:34 被阅读0次

    JS高级

    函数

    • 函数声明

      • 函数声明的时候,函数体不会执行,只要函数被调用的时候才会执行

      • 函数一般用来干一件事情,函数名称一般使用动词

        function 函数名(){
        //函数体
        }

    • 函数表达式

      var fn =function(){
      //函数体
      }

    • 函数的调用

      • 函数体只有在调用的时候才会执行,调用需要()进行调用,可以调用多次

        函数名();
        // 声明函数
        function sayHi() {
        console.log("吃了没?");
        }
        // 调用函数
        sayHi();

    • 函数的参数

      • 形参:声明函数时,给函数设置参数,这个参数没有具体的值,只起到占位作用。
      • 实参:如果函数声明设置了形参,调用时就需要传入对应的参数,这个传入的参数叫实参
    • 函数的返回值

      • 当函数执行完毕时,我们期望函数给我们一些反馈(比如计算的结果返回进行后续的运算)这就是返回值,通过return返回一个返回值。
      • 函数的调用结果就是返回值,可以直接对函数调用结果进行操作。
      • 返回值详解
        • 函数没有 return 返回 undefined
        • 函数 有return 跟在return后面的值就是函数的返回值
        • 函数有return后面没有任何值,返回 undefined
        • 函数使用return语句,这个函数就会在执行完return之后停止并立即退出,return后面的所有代码不再执行。
    • 匿名函数

      • 没有名字的函数
      • 将匿名函数赋值给一个变量,通过变量进行调用
      • 或者匿名函数自调用
    • 自调用函数

      • 匿名函数不能直接通过调用来执行,因此可以通过匿名函数自调用的方式来执行

        (function () {
        alert(123);
        })();

    • 函数是一种数据类型

      • 函数作为参数

        • 函数可以作为另一个函数的参数,在另一个函数中调用
      • 函数作为返回值

        • 函数可以作为返回值从函数内部返回

        function fn(b) {
        var a = 10;
        return function () {
        alert(a+b);
        }
        }
        fn(15)();

    new关键字

    1. new在执行时会做四件事情:
    2. new会在内存中创建一个新的空对象
    3. new 会让this指向这个新的对象
    4. 执行构造函数 目的:给这个新对象加属性和方法
    5. new会返回这个新对象

    this 详解

    对象的使用

    • 遍历对象的属性

    • for in 可以遍历对象的成员

      for (var key in obj){
      console.log(key)//-->属性名
      console.log(obj[key])//--对应的属性值
      }

    • 删除属性

      delete 对象.属性名

    构造函数

    对象的属性和方法叫做对象的成员

    1. 函数内部创建的属性和方法叫做实例对象/对象成员
    2. 跟对象相关的成员,将来使用对象的方式调用
    3. 静态成员:直接给构造函数增加成员
    4. 静态成员不能使用对象的方式调用,使用构造函数调用(Hero.成员)
    5. 实例成员与对象有关,静态成员与对象无关

    原型对象

    1. 每个构造函数都有一个属性,就是原型对象prototype
    2. 构造函数通过原型对象增加的方法和属性,构造函数创建的所有对象都可以访问,而且在在内存中只有一份
    3. 对象通过打点的方式增加属性,而 构造函数.prototype 也是一个对象,也可以通过打点的方式增加方法,而且构造函数创建的所有对象都可以增加了这个方法(语法:构造函数.prototype.方法=function(){})
    4. 使用原型对象增加方法和在构造函数内增加方法的区别:当调用对象的属性或方法,先去找对象的属性或方法,如果对象没有该属性/方法,此时去调用原型中的属性或方法
    5. 对象.proto = 构造函数.prototype (通过构造函数(Hero)创建对象(hero1))
    6. 只要有对象,都有proto这个属性,在原型对象中有个属性叫constructor,这个属性叫构造函数,可以打印出这个构造函数,访问方式,对象.constructor,constructor记录了创建给对象的构造函数,可以判断这个对象是由哪个构造函数创建的

    构造函数 原型对象 实例/对象 之间的关系

    • 构造函数创建对象
      构造函数的原型属性prototype 构造函数 拥有 原型对象
    1. 对象的属性proto 指向 构造函数的原型对象

    原型链

    1. 原型链的顶端是null
    2. s1对象的原型对象的原型对象就是Object构造函数的原型对象
      s1.proto.proto===Object.prototype
    3. 读取属性时,先在对象本身查找,找不到就去原型链里找
    4. 设置属性时,不会搜索原型链,而是给这个对象新增一个属性并赋值
    5. 当我们改变构造函数的prototype时,需要重新设置constructor属性
    6. 先设置原型属性,在创建对象,才可以访问原型对象中的成员

    原型对象的应用

    数组或String中的prototype是不可以重新赋值修改的

    继承

    面向对象三大特征: 封装 继承 多态(抽象)

    继承:类型和类型之间的关系

    继承的目的::把子类型中共同的成员提取到父类型中,代码重用

    原型继承:无法设置构造函数的参数

    借用构造函数(造函数的属性继承)

    1. call()改变函数的this,直接调用函数,call的第一个参数是要改变的指向对象
    2. 在函数内部,通过 call(借用的函数,参数),借用了构造函数继承了属性成员
    3. 借用构造函数的方法只有在构造函数内方法可以继承,通过原型对象增加的方法不能继承

    组合继承

    1. 组合继承:借用构造函数+ 原型继承
    2. 借用构造函数(在函数内部使用call) + 原型继承(子类型.protopyte=父类型.prototype)
    3. 借用构造函数,让teacher继承person里的属性,设置teacher的原型对象,继承person里的方法(teache.prototypr=new Person();),

    函数的进阶

    • 函数声明和函数表达式的区别:函数表达式的变量会提升,结果为undifined,函数声明不会提升

    • if语句内,函数不会提升

    • 函数定义方式:函数也是对象,可以传参,有属性和方法

      var fn=new Function('a','b','console.log(a+b));
      fn(1,2);

    函数的调用方式

    • 普通函数调用:this指向window,谁调用这个方法,this指向谁

      function fn(){
      console.log(this)
      }
      fn();

    • 方法调用:this指向调用该方法的对象

      var obj={
      fn:function(){
      console.log(this)
      }
      }
      obj.fn();

    • 作为构造函数调用【call ()】:this指向由这个构造函数创建的对象

    • 作为事件的处理函数调用:this指向触发该事件的对象

      btn.onclick=function(){
      console.log(this)
      }

    • 作为定时器的参数:this指向window

      setInterval(function(){
      console.log(this)
      },1000)

    ==函数内部的this是由函数调用的时候确定其指向==

    call 、apply 和bind()改变函数中的this

    function fn(x,y){
        console.log(this);
        console.log(x+y);
    }
    fn(5,6) //this-->window
    
    var obj={
        name:'zs'
    }
    fn.call(obj,5,6); //-->obj对象和11
    fn.apply(obj,[1,8]);//fn内需要几个参数,数组中传几个参数
    //-->obj和9
    
    //bind不会调用函数,要想调用需要用一个变量接收bind的返回值
    var f=fn.bind(obj,2,2);
    f();//不用传递参数直接调用
    
    • call方法:
    1. 调用函数,改变函数中的this
    2. 第一参数,设置函数内部this的指向,其他参数,对应函数的参数
    3. 函数的返回值,call的返回值就是fn函数的返回值
    • apply方法:
    1. 调用函数,改变函数中的this
    2. 第一个参数: 设置函数内部this的指向,第二个参数是数组
    3. 函数的返回值,call的返回值就是fn函数的返回值
    • bind方法:
    1. 改变函数中的this,但不会调用函数,而是把函数复制一份
    2. 第一参数,设置函数内部this的指向,其他参数,对应函数的参数
    3. 函数的返回值,call的返回值就是fn函数的返回值

    call的应用

    Array.prototype.getSum=function(){
        this指谁?
    }
    var arr=[1,2,3];
    arr.getSum();//通过数组调用,this指向这个数组
    arr.push(); //数组本身提供了,push、splice方法
    arr.splice(); //删除数组元素  splice(从那一项删除,删除几项)
    

    伪数组

    var Obj={
        0:100,
        1:10,
        2,:11,
        3:20,
        length:4
    };
    

    给这个数组追加属性:

    方法一:

    obj['4']=12; //(数字不能作为变量和属性开头,所以用obj['4'])
    obj.length++;
    

    方法二:

    数组的push方法(让伪数组借用数组的方式)

    Array.prototype.push.call(obj,30);
    //给Array的原型对象push一个对象,
    //并且通过call改变this指向,
    //指向obj,就给obj追加了数组
    

    所有的对象都有toString()这个方法

    • object.toString()--->Object(代表是一个对象) object(这个对象的类型)
    • arr.tostring()-->数组里的值 1,2,3
    • Object.prototype.toString.call(arr) ---> object Array (数组对象的类型)

    apply的应用

    语法:fn.apply(,[])

    常用于把数组展开,传递给前面的方法

    var arr = [5,8,10,2]
    console.log(Math.max(arr))//--.NAN Math.max不能求数组中的最大值
    <!--可以把数组中的每一项展开,传给max,返回最大值-->
    Math.max.apply(null,arr)
    <!--max中的this指向math,所以不用改变指向-->
    Math.max.apply(Math,arr)
    

    bind的应用

    bind和apply、call的区别在于bind不会去调用方法,而是去复制方法

    • 应用一

      var obj = {
      name:'zs',
      fun:function(){
      setInterval(function(){
      console.log(this.name)
      }.bind(this),1000);
      }
      }
      obj.fun()

    • 应用二

      btn.onclick=function(){


      }.bind(obj)

    小结

    • call 和 apply 特性一样
      • 都是用来调用函数,而且是立即调用
      • 但是可以在调用函数的同时,通过第一个参数指定函数内部 this 的指向
      • call 调用的时候,参数必须以参数列表的形式进行传递,也就是以逗号分隔的方式依次传递即可
      • apply 调用的时候,参数必须是一个数组,然后在执行的时候,会将数组内部的元素一个一个拿出来,与形参一一对应进行传递
      • 如果第一个参数指定了 null 或者 undefined 则内部 this 指向 window
    • bind
      • 可以用来指定内部 this 的指向,然后生成一个改变了 this 指向的新的函数
      • 它和 call、apply 最大的区别是:bind 不会调用
      • bind 支持传递参数,它的传参方式比较特殊,一共有两个位置可以传递
          1. 在 bind 的同时,以参数列表的形式进行传递
          1. 在调用的时候,以参数列表的形式进行传递
        • 那到底以谁 bind 的时候传递的参数为准呢还是以调用的时候传递的参数为准
        • 两者合并:bind 的时候传递的参数和调用的时候传递的参数会合并到一起,传递到函数内部

    函数中的其他成员

    • arguments
      • 伪数组,获取到的是函数的实参,实参集合
    • caller
      • 函数的调用者,在全局范围调用的时候caller是null
    • name
      • 函数的名称,字符串类型
    • length
      • 函数的形参个数

    arguments应用

    //当函数的参数个数不固定的时候
    //在函数内部,可以通过arguments获取到实际传过来的参数
    function max(){
        var max = arguments[0];//假设第一个参数为最大值
        for(var i=0,i<arguments.length;i++){
            if(max<arguments[i]){//如果最大值小于遍历的这个参数
                max=arguments[i];//那么让这个参数为最大值
            }
        }
    }
    console.log(max(2,7,9,4)); //-->9
    

    相关文章

      网友评论

          本文标题:JS - 高级

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