Code Monkey home page Code Monkey logo

Comments (32)

lzlu avatar lzlu commented on May 16, 2024 14

个人优化后的版本

Function.prototype.applyOne = function(context){
    context.fn = this;
    eval('context.fn('+(arguments[1]||[]).toString()+')');
    delete context.fn;
}

(我也算参与过1.2k的大项目了么

from blog.

zyg-github avatar zyg-github commented on May 16, 2024 2

原生的apply 支持 参数是对象 如果用eval模拟要完全用字符串拼接 不然会有问题

@jawil
应该吧

var fnStr = 'context[fn]('
    for (var i = 0; i < args.length; i++) {
        //得到"context.fn(arg1,arg2,arg3...)"这个字符串在,最后用eval执行
        fnStr += i == args.length - 1 ? args[i] : args[i] + ','
    }
    fnStr += ')'

改为

var fnStr = 'context[fn]('
    for (var i = 0; i < args.length; i++) {
        //得到"context.fn(arg1,arg2,arg3...)"这个字符串在,最后用eval执行
        fnStr += i == args.length - 1 ? 'args[' + i + ']' : 'args[' + i + ']' + ','
    }
    fnStr += ')'

from blog.

Mryszhang avatar Mryszhang commented on May 16, 2024 1

sayHello.applyFive(obj,['hello']是有问题的,eval解析时hello未定义,用toString也是不行的

from blog.

jawil avatar jawil commented on May 16, 2024 1

当初考虑的情况确实只是最简单的字符串,因为只是提供一种实现的思维,感谢指正 @zyg-github

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 16, 2024

好巧,我们今天的文章同时讲到了call和apply的模拟实现

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 16, 2024

不过现在的bind的模拟实现其实是有个小问题的,我专门私信了颜海镜求证了这个问题。

from blog.

jawil avatar jawil commented on May 16, 2024

length问题?@mqyqingfeng 同事朋友去51信用卡遇到这个面试题,我上周写了一半,今天看见你发了,我也赶紧写完,发现思路都差不多,我主要是先实现apply引出的。。。😄

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 16, 2024

并不是哦,如果你比较MDN英文版和中文版的实现,就会发现这个问题。先卖个关子,明天发布的文章讲解bind的模拟实现就会讲到这个问题。(๑•̀ㅂ•́)و✧

from blog.

jawil avatar jawil commented on May 16, 2024

恩恩,我会关注呢,反正你一发就会有邮件推送😄

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 16, 2024

仔细看了你的这篇文章,嗯,觉得……哈哈,建议楼主在整理资料的过程中慢慢找到自己的思路去表达,否则按照参考文章的思路去写,容易显得似曾相识。我自己也有这样的问题,与楼主共勉。

from blog.

xumeiyan avatar xumeiyan commented on May 16, 2024

看了有些文章,最后那个三元判断是这种的
this instanceof F ? this : context || window
有点迷糊

from blog.

jawil avatar jawil commented on May 16, 2024

在非严格模式下,走后面逻辑的话此时的this就是指向window,其实是一个东西。。。@xumeiyan

from blog.

jawil avatar jawil commented on May 16, 2024
Function.prototype.applyTwo = function(context) {
        var argsPar=arguments[1]
        context.fn = this;
        var args = [];

        for (var i = 0, len = argsPar.length; i < len; i++) {
            args.push('argsPar[' + i + ']');
        }
        var str='context.fn(' + args + ')'
        eval('context.fn(' + args + ')');

        delete context.fn; //执行完毕之后删除这个属性
    }
    //测试一下
var jawil = {
    name: "jawil",
    sayHello: function(age) {
        console.log(this.name, age);
    }
};

var lulin = {
    name: "lulin",
};

jawil.sayHello.applyTwo(lulin, ['hello']) //lulin 24

改成这样就ok了@Mrzhangyasheng

from blog.

Thinking80s avatar Thinking80s commented on May 16, 2024

都是基础啊,理解原理了自然就可以写出来了

from blog.

leat14536 avatar leat14536 commented on May 16, 2024

大多数(可能是所有)原生对象上的方法的prototypeundefined, 比如 Array.prototype.push.prototype === undefined. 于是这样使用会报错:

var obj = {0: 'a', 1: 'b', length: 2}
 // 原生bind
 var each1 = Array.prototype.forEach.bind(obj, function(item) {
     console.log(item)
 })
 var each2 = Array.prototype.forEach.bindOne(obj, function (item) {
     console.log(item)
 })

 each1() // a b
 each2() // Uncaught TypeError: Function has non-object prototype 'undefined' in instanceof check

个人做了这样的优化

var F = function () {};
F.prototype = this.prototype || Object.create(null);

from blog.

jawil avatar jawil commented on May 16, 2024

感谢补充优化,不过Object.create(null)好像是ES5的方法,用在这里hack好像不太合适,不过也没事,其实Object.create的也很好模拟实现 @leat14536

from blog.

axuebin avatar axuebin commented on May 16, 2024

请教一个问题,您实现apply的第三步中通过以下方式来实现当this为空时指向window

var context = context || window

可是,当this为空时,apply应该是不能传递参数的吧?

applyFive([1,2])这样是不行的

这块我有点不明白,请您指教一下。。

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 16, 2024

@axuebin 处理的是这种情况 fn.apply(null, [1, 2])

from blog.

jawil avatar jawil commented on May 16, 2024

感谢@mqyqingfeng 百忙之中作出回答😂

from blog.

axuebin avatar axuebin commented on May 16, 2024

明白了。。我之前有一个地方写错了,导致apply()即没this又没参数时出错了。。谢谢~

from blog.

lkangd avatar lkangd commented on May 16, 2024

不错不错,厉害,不过applyFive没传参的直接执行的时候没有执行delete context[fn]。

    if (args == void 0) { //没有传入参数直接执行
        var returnValue = context[fn]();
        delete context[fn];
        return returnValue;
    }

from blog.

bravepg avatar bravepg commented on May 16, 2024

image

博主真厉害,按照您的步骤进行到如图标红的一步,发现args
image
是上图中的第一行代码(是个对象),但是却有个length属性,能不能解释一下为什么啊?

from blog.

mqyqingfeng avatar mqyqingfeng commented on May 16, 2024

@gaopeng0108 arguments 对象是一个类数组对象,就是会有一个 length 属性,你在浏览器中可以看到这个属性,可以参考这篇文章 mqyqingfeng/Blog#14

from blog.

hsroad avatar hsroad commented on May 16, 2024

飚一句zanghua,前端感觉真TM任重而道远

from blog.

BlaStone avatar BlaStone commented on May 16, 2024

apply在没有传参的时候直接返回了contextfn,但是好像没有把context的fn删除呢

from blog.

lesini avatar lesini commented on May 16, 2024

厉害!

from blog.

jiamianmao avatar jiamianmao commented on May 16, 2024

莫非你就是1024康先生,麻烦送一码。1024。

from blog.

lizhongzhen11 avatar lizhongzhen11 commented on May 16, 2024

哈哈哈哈哈,我前几天在某个群里也看到这条题目,我今天想了半天,偶然意识到可以这样:

// ...省略
obj.fn = fn
let result = obj.fn(...arr)
delete obj.fn
return result

我写完觉得这样是不是不好,然后我就网上搜,发现你大致也是这样做的,开心~

from blog.

tgzzl avatar tgzzl commented on May 16, 2024

from blog.

chuanHH avatar chuanHH commented on May 16, 2024

from blog.

LiXinLeLe avatar LiXinLeLe commented on May 16, 2024

bind方法传递给调用函数的参数可以逐个列出,也可以写在数组中。

这句感觉不太对吧,需要逐个列出,不可以放在数组中

from blog.

chuanHH avatar chuanHH commented on May 16, 2024

from blog.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.