zoukankan      html  css  js  c++  java
  • 面试:call、apply、bind原理以及自己手写简易模式

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title>call-apply-bind的实现</title>
        </head>
        <body>
            <script type="text/javascript">
                // 1.call的使用  call(ctx,...args) ctx:执行函数需要改变的this对象,args:执行函数需要传入的参数 call改变函数this指向
                function fn(name) {
                  console.log(this, name); // window 老王
                }
                fn('老王');
                // 创建一个 obj
                let obj = {name: '老李'}
                // 通过call执行
                fn.call(obj, '我是谁') // {name: "老李"} "我是谁"  [注:如果有多个参数在后面接着即可]
                
                // 2.apply的使用 apply(ctx, array) ctx:执行函数的this指向; array:传入一个数组,我将数组的每一项作为函数的参数
                function fn1(name1, name2) {
                  console.log(this, name1, name2);
                }
                let obj1 = {name: '老王'};
                let arr = ['小王', '小明'];
                fn1.apply(obj1, arr) // {name: "老王"} "小王" "小明"
                // 小结: call传入的是不定参数,apply传入的是一个具体的数组,数组里面包含所有参数
                // 例子:求数组中最大值
                let list = [1,2,3,4,9,20,6,8],
                    max = Math.max.apply(null, list);
                    console.log(max) // => 20
                // 3.bind的使用
                // bind(ctx, arg...): bind 和call方法的参数是一样的,只是用法有些区别
                // bind执行后返回值是一个函数,
                // 这个函数的this被定死(绑定)为传入的ctx对象且不可变,
                // 这个函数的参数也被定死(绑定)为 ...arg且不可变
                function fn3(age) {
                  console.log(this, age)
                }
                let newoObj = {name: '小明'}
                let fun = fn3.bind(newoObj, 18)
                fun() // {name: "小明"} 18
                // 参数和this都被绑死
                fun.bind(window, 18)() // {name: "小明"} 18
                fun.call(window, 18) // {name: "小明"} 18
                fun.apply(window, [18]) // {name: "小明"} 18
                fun(18) // => {name: "小明"} 18
                // 小结:通过bind绑定过后的方法,无论怎么执行都无法修改this指向和参数的,注:以上三个方法如果不传第一个参数,this指向在非严格模式下均为window
                
                // 面试题:
                function fn() {
                  console.log(this)
                }
                let objtest = {name: '老王'}
                
                fn.call(objtest) // {name: "老王"} call改变函数this指向
                
                fn.call.call(function () {
                  console.log(this) // window
                }) 
                
                fn.call.call.call.call(function () {
                  console.log(this) // {name: "老王"}
                }, objtest) 
                /*****************************************************/
                // 1、手写call (1)改变this指向  (2)处理传入的参数
                Function.prototype.myCall = function(ctx){
                    // 先将fn挂在context上
                    ctx.fn = this
                    var args = [...arguments].slice(1)
                    var res = ctx.fn(...args)
                    // ctx调用fn 使fn中的this指向到ctx上
                    delete ctx.fn
                    return res
                }
                // 2、手写apply (1)改变this指向  (2)参数通过数组的形式
                Function.prototype.myApply = function(ctx){
                    // 先将fn挂在context上
                    ctx.fn = this
                    var res
                    if(arguments[1]){
                        res = [...arguments[1]];
                    } else {
                        res = ctx.fn;
                    }
                    delete ctx.fn
                    return res
                }
                // 3、手写bind  bind终生绑定不立即执行返回一个新函数,传参和 call 是一样的
                Function.prototype.myBind = function(context) {
                    if (typeof this !== 'function') {
                        throw new TypeError('Error')
                    }
                    // 返回一个绑定this的函数,这里我们需要保存this
                    const _this = this
                    const args = [...arguments].slice(1)
                    //返回一个函数
                    return function F() {
                        // 因为返回一个函数,我们可以new F()需要判断能当做构造函数吗
                        if (this instanceof F) {
                            return new _this(...args, ...arguments)
                        }
                        return _this.apply(context, args.concat(...arguments))
                    }
                }
                let testObj = {
                    name: '测试手写'
                }
                let testArr = ['小王', '小明'];
                function test(){
                    console.log(this, name);
                }
                
                test.myCall(testObj) // {name: "测试手写", fn: ƒ}
                
                function test2(name1, name2) {
                  console.log(this, name1, name2);
                }
                
                test2.apply(testObj,testArr) // {name: "测试手写"} "小王" "小明"
                
                function foo() {
                    console.log(this.name) // 测试手写
                    console.log(arguments) // ['a','b','c']
                }
                
                foo.myBind(testObj, 'a', 'b', 'c')() 
            </script>
        </body>
    </html>
  • 相关阅读:
    深入浅出新一代云网络——VPC中的那些功能与基于OpenStack Neutron的实现(三)-路由与隧道
    从这两年的云计算行业安全黑板报来看看云安全现状
    深入浅出新一代云网络——VPC中的那些功能与基于OpenStack Neutron的实现(二)-带宽控制
    云环境下的安全服务架构
    深入浅出新一代云网络——VPC中的那些功能与基于OpenStack Neutron的实现(一)-简述与端口转发
    OpenStack修复影响宿主机的QEMU漏洞CVE-2017-2615
    OpenStack Newton版本Ceph集成部署记录
    团队博客汇总
    谷歌浏览器将任意网页转成中文
    password_hash加密
  • 原文地址:https://www.cnblogs.com/lhl66/p/13816988.html
Copyright © 2011-2022 走看看