函数四种调用方式(三种+上下文模式)

本文详细介绍了JavaScript中函数的三种调用方式:全局函数、对象方法和构造函数,并重点讨论了函数的上下文调用,包括call()、apply()和bind()的用法和异同。此外,还提到了如何转换伪数组,以及数据类型检测和借用构造函数继承的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数的三种调用方式

  • 全局函数
  //全局函数 this指向window 因为fn全局函数是window的一个属性
        function fn() {
            console.log(this);//window

        }
        // window.fn();
        fn();
  • 对象方法
 //对象的方法
        var p = {
            name: '张三',
            age: 15,
            sayHi() {
                console.log(this);//p对象
                console.log(this === p);//true
            }
        }
        p.sayHi();
        //将fn函数赋值给对象的sayHi
        p.sayHi = fn;
        p.sayHi();//此时执行fn中代码 this指向p
  • 构造函数
  //构造函数 new会做四件事 会将this指向new创建的对象
        function Stu(name, age) {
            this.name = name;
            this.age = age;
        }
        var s = new Stu('李四', 18);
        console.log(s);

        //普通函数 相当于window.Stu()调用  this是window 给window动态加属性
        var s1 = Stu('王五', 20);
        console.log(s1);//没有返回值 结果undefined
        console.log(name);//王五
        console.log(age);//20
	this谁调用 this指向谁
	全局函数中 this指向window
	对象方法中 this指向对象
	构造函数中 this指向new创建的对象
	定时器中 this默认指向window
  • 函数的三种调用方式的共同点
    this的指向是确定的无法修改的
函数的上下文调用
  • 可以动态修改this的指向
  • call()
    语法 函数名.call(修改this的指向,arg1,arg2...)
function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2);//this指向window
        fn.call({ name: '张三' }, 10, 20);//修改后this指向这个对象
  • apply()
    语法 函数名.apply(修改this的指向,[arg1,arg2...])
    第二个参数是数组或伪数组 会自动遍历数组或伪数组的每一个元素给函数的形参赋值
function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2);//this指向window
        fn.apply([1, 2], [30, 40]);//修改后this指向这个数组 
  • bind()
    语法 函数名.apply(修改this的指向,arg1,arg2...)
    bind()不会执行这个函数 而是会返回一个修改了this之后的新函数 然后再对这个新函数进行传参

      bind ()修改this的指向一般用于回调函数 如定时器
    
function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fn(1, 2);//this指向window

        //bind与call不同的是 它不会执行这个函数 
        //而是会返回一个修改了this之后的函数
        //然后在堆返回的函数传参
        //bind一般用于回调函数中 如定时器
        var fn2 = fn.bind([2, 22, 222]);
        fn2(1, 11)

        //定时器的this默认指向window 可以用bind修改this的指向
        //匿名函数
        setTimeout(function () {
            console.log(this);
            //回调函数中修改this 此时this执行对象      
        }.bind({}), 2000);

        //表达式函数
        var test = function () {
            console.log(this);
        }
        setTimeout(test.bind([10, 20]), 1000);
  • 上下文调用模式三种语法的异同点
    • 相同点: 作用都是动态修改this的指向
    • 不同点传参方式不一样
  • 上下文调用模式三种方法 其实是属于Function构造函数的原型的 意味着js中所有的函数都能使用上下文调用修改this的指向
  • 修改的this只能是引用类型
    如果将this改为值类型 会自动转成基本包装类型
    如果将this改为undefined和null 程序不会报错 也不会修改 this依旧指向window
    如果没有传参 this依旧指向window

  • 伪数组转数组
    方法1 声明空数组 遍历伪数组 往空数组中追加
  //伪数组转数组
        var weiArr = {
            0: 10,
            1: 20,
            2: 30,
            length: 3
        }
        //方法1
         var arr =[];
         for(var i=0;i<weiArr.length;i++){
            arr.push(weiArr[i])
         }
         console.log(arr);

方法2 声明空数组 通过apply自动遍历伪数组

        //方法2
        var weiArr = {
            0: 10,
            1: 20,
            2: 30,
            length: 3
        }
        var arr = [];
        arr.push.apply(arr, weiArr)
        console.log(arr);

方法3 通过数组的slice()方法
传入0 返回数组自身
通过数组的原型调用slice方法
通过call修改this的指向

  //方法3
  var weiArr = {
            0: 10,
            1: 20,
            2: 30,
            length: 3
        }
        // var res = arr.slice(0);//会返回一个新数组 传入0 返回自身
        // console.log(res);
        var res = Array.prototype.slice.call(weiArr, 0);
        console.log(res);
  • 伪数组排序
 //伪数组排序
        var weiArr = {
            0: 20,
            1: 1,
            2: 5,
            3: 2,
            4: 10,
            length: 5
        }

        Array.prototype.sort.call(weiArr, function (a, b) {
            return a - b;
        })
        console.log(weiArr);
  • 求数组最大值
    方法1 打擂台
  //数组最大值
        //方法1
        var arr = [200, 50, 3, 60, 9, 66];
        var max = arr[0];
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i]
            }
        }
        console.log(max);
        
       

方法2 Math.max() 用apply将参数变成数组

 //方法2
        //Math.max([],[]...) 用apply将参数变成数组 
        console.log(Math.max.apply(Math,arr));
	思考题: 数组调用toString结果与对象调用toString结果为什么不一样??
	因为Array的原型中有toString Object的原型中也有toString
	根据变量访问原型链成员的构造 如果数组调用toString会访问Array原型中的toString
		 //Array.prototype.toString() 底层调用的是 数组.join()
        //Object.prototype.toString() 返回固定的字符串 [Object 数据类型]
        console.log([].toString());//空字符串
        console.log({}.toString());//[object Object]

        console.log([1,2,3].toString());//1,2,3
        console.log({name:'张三'}.toString());//[Object Object]
万能数据类型检测法

typeof关键字检测null和array都会得到object 无法检测

console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call([]));//[object Array]
借用构造函数继承

借用Person中的两行代码赋值给Stu函数 通过call修改this为Stu函数的this
只能继承this点出来的属性 如果是实例化点出来的属性无法继承

 function Person(name, age) {
            this.name = name;
            this.age = age;
        }
        var p = new Person('张三', 18);
        console.log(p);

        function Stu(name, age) {
            // this.name = name;
            // this.age = age;
            //  Person(name,age);
            //借用构造函数继承 通过call修改this为Stu函数中的this
            Person.call(this, name, age);
        }
        var s = new Stu('学生', 18)
        console.log(s);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值