JavaScript - js进阶 - this与函数的四种调用模式/借调方法/借调应用/借调的传参区别

普通函数 对象方法 构造函数

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>this 与 函数的关系</title>
    </head>
    <body></body>

    <script>
        // 函数(function)里面必有this, this始终指向调用者(谁调用指向谁)

        // 1. 普通函数: 有名 和 函数表达式
        // this: 指向window

        function fn1() {
            // window.fn1 = function(){}
            console.log(this);
        }

        fn1(); // window.fn1()

        const fn2 = function () {
            console.log(this);
        };
        fn2(); // window.fn2()

        // 2. 对象方法: 函数在对象的内部, 属于对象的属性的一个方法
        const obj = {
            name: "对象",
            fn3: function () {
                console.log(this); // fn3一定是obj来调用, this指向对象obj
            },
        };

        obj.fn3();

        // 3. 构造函数: 用法不同, 用new调用函数: this指向产生的对象
        function Student(name, age) {
            console.log(this);
        }

        new Student("钟馗", 200); // 产生内存, 产生对象(构造函数this指向对象), 执行构造函数, 返回内存地址

        // 扩展: 回调函数里面的this: 普通的回调函数,里面的this一定指向 window对象
        let arr = [1, 2, 3];
        arr.forEach(function () {
            console.log(this); // 指向window
        });

        function fn4(fn) {
            // fn要求是一个回调函数: 普通调用
            fn(); // 相当于  window.fn()
        }

        fn4(function () {
            console.log(this); // window
        });

        // 总结
        // 虽然this与函数的关系有很多种模式: 但是本质永远是: 谁调用this就指向谁
    </script>
</html>

借调模式

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>this 与 函数的关系 - 借调关系</title>
    </head>
    <body></body>
    <script>
        // 借调: 高手所为

        // 借调的条件: 1. 当前要解决某个问题   2. 知道别的函数能解决这个问题  3. 函数的内部用到了this: 可以被修改
        // 借调的本质: 修改被借调函数内部的this

        // 借调方式有三种
        /*
        call: 一次性
        apply: 一次性

        bind: 永久性

        语法: 差不多
        函数名.借调(新对象)
    */

        const richWoman = {
            name: "富婆",
            getChild: function () {
                console.log(this.name + "重金求子");
            },
        };

        // 普通调用
        richWoman.getChild();

        // 屌丝重金求子
        const ds = {
            name: "屌丝",
        };

        // 借调: 借用别人的东西(函数), 节省代码: 往往只要修改函数里面的this即可(指向的对象)

        // richWoman.getChild: getChild里面得到this指向richWoman
        // 如何让getChild里面的this指向ds对象呢?

        // 借调实现
        // 1. call: 函数名.call(新对象)   新对象就是用来改变函数里面的this
        richWoman.getChild.call(ds); // this = ds

        // 2. apply: 函数名.apply(新对象)   新对象就是用来改变函数里面的this
        richWoman.getChild.apply(ds); // this = ds 跟call没有任何区别

        // 3. bind: call和apply是一次性调用: 调用完了就结束了(直接调用): bind叫永久性借调: 拿过来之后会复制一份, 不会直接运行
        richWoman.getChild.bind(ds);
        console.log(richWoman.getChild.bind(ds)); // f 返回一个新函数(里面的this发生了永久性的改变)

        // 3.1 一次性使用:直接在后面再加一个()
        richWoman.getChild.bind(ds)();

        // 3.2 多次使用: 先用变量保存借调结果, 通过变量不断调用
        const newGetChild = richWoman.getChild.bind(ds);

        newGetChild();
        newGetChild();
        newGetChild();
        newGetChild();

        // 总结
        // 任何函数: 一定可以被借调
        // 借调: 高手所为(能用最好: 效率高; 用不了不影响开发: 自己写函数)
    </script>
</html>

借调应用

<!DOCTYPE html>
<html lang="zh-CN">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>借调 - 应用</title>
    </head>

    <body>
        <script>
            // 借调: 发生最多的 伪数组与数组的关系
            // 伪数组: 有下标, 可以下标访问, 也可以使用for循环遍历
            // 但是伪数组不能调用数组的API的: map\fliter\forEach

            // 实际开发中: 遇到伪数组 要用数组的API的时候 采用借调模式

            let obj = { 0: "安琪拉", 1: 18, 2: "女", 3: "扔个球", length: 4, other: "其他" };

            // 对象: 拥有下标属性,同时拥有length属性: 就可以称之为伪数组
            // obj.forEach()        // 不能使用(不是数组: 不能调用数组API)

            // 只有数组可以调用数组的API 或者借调

            // 1. 直接借调数组的forEach
            Array.prototype.forEach.call(obj, function (item, index) {
                console.log(item, index);
            });

            // 2. 可以将伪数组转成数组
            // 手动版本
            let arr = [];
            for (let i = 0; i < obj.length; i++) {
                // obj[i]: 对象的每个属性值: 数字下标的
                arr.push(obj[i]);
            }
            // console.log(arr)
            arr.forEach(function (item, index) {
                console.log(item, index);
            });

            // 自动版本: 借调, Array.prototype.slice() : 截取数组, 默认从下标为0的元素开始, 到length - 1结束
            // 可以借调: 改变里面的this 变成对象
            let newArr = Array.prototype.slice.call(obj);
            newArr.forEach(function (item, index) {
                console.log(item, index);
            });

            // 总结
            // 借调: 伪数组借调数组的API
            // 1. 可以直接借调数组的方法,用来实现伪数组的操作: Array.prototype.API.call(对象,其他参数)

            // 2. 可以借调Array.prototype.slice API实现将伪数组 变成数组

            let str =
                "家用电器,手机,运营商,数码,电脑,办公,家居,家具,家装,厨具,男装,女装,童装,内衣,美妆,个护清洁,宠物,女鞋,箱包,钟表,珠宝,男鞋,运动,户外,房产,汽车,汽车用品,母婴,玩具乐器,食品,酒类,生鲜,特产,艺术,礼品鲜花,农资绿植,医药保健,计生情趣,图书,文娱,教育,电子书,机票,酒店,旅游,生活,理财,众筹,白条,保险,安装,维修,清洗,二手,工业品";

            let str1 =
                '[{"href":"https://jiadian.jd.com/","text":"家用电器"},{"href":"https://shouji.jd.com/","text":"手机"},{"href":"https://wt.jd.com/","text":"运营商"},{"href":"https://shuma.jd.com/","text":"数码"},{"href":"https://diannao.jd.com/","text":"电脑"},{"href":"https://bg.jd.com/","text":"办公"},{"href":"https://channel.jd.com/home.html","text":"家居"},{"href":"https://channel.jd.com/furniture.html","text":"家具"},{"href":"https://jzjc.jd.com/","text":"家装"},{"href":"https://channel.jd.com/kitchenware.html","text":"厨具"},{"href":"https://phat.jd.com/10-603.html","text":"男装"},{"href":"https://phat.jd.com/10-507.html","text":"女装"},{"href":"https://phat.jd.com/10-156.html","text":"童装"},{"href":"https://channel.jd.com/1315-1345.html","text":"内衣"},{"href":"https://beauty.jd.com/","text":"美妆"},{"href":"https://channel.jd.com/beauty.html","text":"个护清洁"},{"href":"https://channel.jd.com/pet.html","text":"宠物"},{"href":"https://phat.jd.com/10-184.html","text":"女鞋"},{"href":"https://phat.jd.com/10-183.html","text":"箱包"},{"href":"https://channel.jd.com/watch.html","text":"钟表"},{"href":"https://channel.jd.com/jewellery.html","text":"珠宝"},{"href":"https://phat.jd.com/10-185.html","text":"男鞋"},{"href":"https://phat.jd.com/10-109.html","text":"运动"},{"href":"https://phat.jd.com/10-272.html","text":"户外"},{"href":"https://xinfang.jd.com/","text":"房产"},{"href":"https://car.jd.com/","text":"汽车"},{"href":"https://che.jd.com/","text":"汽车用品"},{"href":"https://baby.jd.com/","text":"母婴"},{"href":"https://toy.jd.com/","text":"玩具乐器"},{"href":"https://food.jd.com/","text":"食品"},{"href":"https://jiu.jd.com/","text":"酒类"},{"href":"https://fresh.jd.com/","text":"生鲜"},{"href":"https://china.jd.com/","text":"特产"},{"href":"https://art.jd.com/","text":"艺术"},{"href":"https://channel.jd.com/1672-2599.html","text":"礼品鲜花"},{"href":"https://nong.jd.com/","text":"农资绿植"},{"href":"https://health.jd.com/","text":"医药保健"},{"href":"https://channel.jd.com/9192-9196.html","text":"计生情趣"},{"href":"https://book.jd.com/","text":"图书"},{"href":"https://mvd.jd.com/","text":"文娱"},{"href":"https://education.jd.com/","text":"教育"},{"href":"https://e.jd.com/ebook.html","text":"电子书"},{"href":"https://jipiao.jd.com/","text":"机票"},{"href":"https://hotel.jd.com/","text":"酒店"},{"href":"https://trip.jd.com/","text":"旅游"},{"href":"https://ish.jd.com/","text":"生活"},{"href":"https://licai.jd.com/","text":"理财"},{"href":"https://pro.jd.com/mall/active/4EYjXQ6xjnM9TgeSjuMRE8ACEk6q/index.html","text":"众筹"},{"href":"https://baitiao.jd.com/","text":"白条"},{"href":"https://bao.jd.com/","text":"保险"},{"href":"https://anzhuang.jd.com/","text":"安装"},{"href":"https://jdwx.jd.com/","text":"维修"},{"href":"https://cleanclean.jd.com/","text":"清洗"},{"href":"https://2.jd.com/","text":"二手"},{"href":"https://mro.jd.com/","text":"工业品"}]';

            console.log(JSON.parse(str1));
        </script>
    </body>
</html>

借调 - 区别 - 传参区别

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>借调 - 区别 - 传参区别</title>
</head>

<body>
    <script>
        // 借调: 所有借调的第一个参数一定是对象, 如果不想改: 可以使用原来的对象, 或者null
        // 函数.call(null)  函数.call(原来的对象)

        // 借调的函数: 可能本身需要参数

        // call和bind是一样的: call/bind(对象,顺序传参)
        // apply: apply(对象,[数组传参])

        function add(a, b) {
            console.log(a + b)          // 函数没有用到this: 改不改this都不影响代码执行
        }

        // 借调传参的问题
        add.call(null, 1, 2)
        add.bind(null, 3, 4)()

        // apply特殊
        // add.apply(null, 2, 3)        // 错误: 报错
        add.apply(null, [2, 3])

        // call和apply实现的功能一模一样: 为什么要有两个呢? 
        // 方便调用者: 如果数据是数组用apply, 如果非数组: 用call


        let obj = { 0: '安琪拉', 1: 18, 2: '女', 3: '扔个球', length: 4, other: '其他' }

        // 需求: 使用forEach遍历obj对象: forEach本身只有一个形参 回调函数
        Array.prototype.forEach.call(obj, function (item, index) {
            console.log(item, index)
        })

        // apply只能接收数组
        Array.prototype.forEach.apply(obj, [function (item, index) {
            console.log(item, index)
        }])

        // 以后直接使用call
        // map(function(){}) filter(funciton(){}) forEach(function(){}) 都只有一个参数: call最方便
    </script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Henry_ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值