js 函数三种角色;四种继承;call,apply ,bind ;类数组转数组

函数的三种角色

  1.普通函数   形参实参  arguments   return   执行过程 
  			 1.形成私有作用域->2.形参赋值->3.变量提升->4.对this进行指向->5.代码从上到下执行->6.作用域是否销毁
	function fn(){}
  2.构造函数(类) 
            1.形成私有作用域->2.形参赋值->3.变量提升->4.对this进行指向->5.创建空对象->6.让this指向这个空的对象->7.代码从上而下执行->8.把this return 出去->9.作用域是否销毁
            2.this指向实例
            3.如果return一个基本数据类型值,不会影响默认返回的this,如果return一个引用数据类型值,把默认返回的对象覆盖
	 function Fn(){ this.x = x }   

	var f = new Fn
  3.对象
    function Fn(){
               
        }  
        fn() 
        fn.num = 1
        var f = new Fn 
        console.log(f.num); //undefined   f不能找到它的私有属性   内置属性不能修改
        console.log(fn);//fn(){}
可枚举属性
	可枚举属性:1.对象的私有属性  2.给类上面新增扩展的属性
	不可枚举属性:对象或原型中天生自带的属性属于不可枚举属性
//for in 循环可以列举出所有的可枚举属性
   var obj = {x:1,y:2,z:3}
    for(var key in obj){
        console.log(key); //x  y  z  //循环属性名  for  in  
        
    } 

    function Fn(){
        this.a =100;
        this.b= 200
    }
    Fn.prototype.getX =function(){

    }
    var f = new Fn//{a:100,b:200}
  /*   for(var key in f){
        console.log(key);//a b  getX
        
    } */

四种继承

原型继承
	类b继承了类A的私有属性以及公有属性,这种继承方式为原型继承
  function A(){
            this.getY = function(){
                console.log(200);
                

            }

        }
        A.prototype.getX = function(){
            console.log(100);
            
        }
        function B(){

        }
        B.prototype = new A   // {getY:f}把大A实例的空间地址给了B的原型
        var b = new B
        b.getY() //200
        b.getX() //100
        //b通过__proto__找到B的prototype,里面没有getX,会继续通过prototype
中间类继承
 function sum(){
        //arguments.pop()  //arguments找不到数组上的方法  它是一个类数组,不是Array的实例,不能使用Array原型上的方法

        //直接修改arguments的__proto__的空间地址,使其指向Array的原型,
        arguments.__proto__ = Array.prototype;
        arguments.pop()
        console.log(arguments); //IE10一下不兼容
        
    }
   sum(100,2,3,56,78,45,36)
call继承
	在类B中,调用了类A,并且通过call改变了类A中this指向,使其指向B的实例,这样类B创建的实例就有了类A的私有属性,这种继承就是call继承
 function A(){
        //this --- B的实例   给小b新增键值对
        this.a = 100
    }
    function B(){
        A.call(this)//this -- 大B的实例  ---  b   让A执行
    }
    var b = new B
    console.log(b);//{}  {a:100}
寄生组合继承
	解决了继承公有和私有属性
//Object.create   创建一个空对象   
    //Object.keys  获取对象的所有属性名放到一个数组中   Object values  获取对象的所有属性值放到一个数组中 
    var obj = {age:1,hh:'欢迎'}
    var o = Object.create(obj)
    console.log(o);
    


    function A(){

    }
    A.prototype.getX = function(){

    }
    function B(){
        A.call(this)//继承私有属性
    }
    B.prototype = Object.create(A.prototype) //继承公有属性
    //为了防止B修改B的原型时,修改了A的原型,所以使用Object.create方法
    var b = new B

call apply bind

call
 call  
      在Function的原型上,Function.prototype
      所有函数都可以获取到call
      Function.prototype.call
      call 可以改变函数this指向  call是一个函数
  call的参数
      1.如果call不传参,那么函数中this指向window
	  2.如果有一个参数,那么就是指向第一个实参  在非严格模式下,传null和undefined都指向window
      3.如果严格模式下,如果没传或传入undefined,this就是undefined,如果传null,this指向null   'use strict'  严格模式
	  4.从第二个参数开始,都会一一传给fn 
  call的this   call点前面的fn
        fn通过__proto__先找到Function原型中的call方法,让call方法执行,call运行时,改变 call中thisthis指向,fn中的this指向call的第一个参数,并且让  call中this   执行


        function fn1(){
            console.log(100);
            console.log(this);
        }
        function fn2(){
            console.log(200);
        }
        //fn.call(1)
        fn1.call.call.call.call(fn2);
        1. fn1.call.call.call -->this--> fn2;
        2. fn1.call.call.call()

        1.fn2--> this 没有变
        2.fn2();

        1.先执行后面的call方法(这个call方法中的this是fn1.call);是改变fn1.call中的this指向fn2;并且让fn1.call运行;
        2. 当fn1.call运行时,改变fn.call中的thisthis指向没有发生改变,继续让fn1.call中this执行,也就是让fn2运行;
apply
	1.改变this指向,传参不同,第二个参数必须是一个数组
    2.传入数组,但fn实际接收的仍然是一个一个接收
    3.不想改this,可以占位  传 this null  都指向window
  function fn(a,b){
            console.log(a,b);
            console.log(this);
        }
        fn.apply(null,[100,220])

bind
 bind  预处理this
	 1.在bind函数中,将fn进行包装和处理,改变了fn里面的this指向,并且返回一个改变this之后的新函数
     2.bind 在IE8以下不兼容
 function xn(a,b){
            console.log(a,b);
            
            console.log(this);
            
        }
        var f = xn.bind([1,2],300,400)  
        f(100,200)  //在bind传和在f传一样  但是bind的优先级高  f传的不改变

类数组转数组

    类数组 arguments   没有prototype的属性    元素集合
    arguments 直接指向Object的原型 调用不了Array上的方法
  //1.for循环
      function sum() {
            var ary = [];
            for (var i = 0; i < arguments.length; i++) {
                ary.push(arguments[i])
            }
            console.log(ary);

        } 
    //2.slice循环
        //ary.slice()
        function sum() {
            Array.prototype.newSlice = function () {
                let aox = [];
                for (var i = 0; i < this.length; i++) {
                    aox[aox.length] = this[i]
                }
                return aox        
            }
            var ary = Array.prototype.newSlice.call(arguments)
            return ary
        }
        console.log(sum(1, 2, 3, 44, 5, 66, 88, 45, 66));



  //3.封装一个类数组转数组    兼容IE678
        var div1 = document.getElementsByTagName('div')
        function toArray(likeAry){
            var ary = [];
            //
            try{
                //如果try中代码报错, 立即执行catch中代码  不会影响下面的代码执行,一般情况,代码遇到报错就会立即停止
                //如果不报错,就不再走catch
                ary = Array.prototype.newSlice.call(likeAry) //这个方法在IE678不兼容  运行会报错
            }catch(e){
                console.log(e);
                
                //e:代表try中代码的错误信息
                for (var i = 0; i < likeAry.length; i++) {
                    ary.push(likeAry[i])
                }
            }
            return ary
        }(div1)
        var newAry = toArray(div1)
        console.log(newAry);
        
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值