Giter VIP home page Giter VIP logo

Comments (35)

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024 28

@dowinweb 像 ES5 的 map、reduce、forEach、find 等等函数,第二个参数都是 context,这是需要开发者写的时候传入的,这其实还算是个蛮常见的场景,举个例子:

function Greet() {
  this.prefix = 'Hello'
  this.friends = ['dowinweb', 'kevin']
}

Greet.prototype.sayHello = function(){
  var self = this;
  var res = this.friends.map(function(item){
        return self.prefix + ' ' +  item
  })
  return res
}

var greet = new Greet();
console.log(greet.sayHello()) // [ "Hello dowinweb", "Hello kevin" ]

一般 map 里的函数,如果要使用外部 this 的值,需要通过 var self = this 这种形式。

其实我们可以写的更加优雅,就是利用 context 这个参数:

function Greet() {
  this.prefix = 'Hello'
  this.friends = ['dowinweb', 'kevin']
}

Greet.prototype.sayHello = function(){
  var res = this.friends.map(function(item){
        return this.prefix + ' ' +  item
  }, this)
  return res
}

var greet = new Greet();
console.log(greet.sayHello())  //  // [ "Hello dowinweb", "Hello kevin" ]

这个算是一个小技巧吧~

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024 1

@iiicon 函数柯里化是指将一个 n 元函数转化为 n 个一元函数,我觉得这个例子叫做高阶函数更好些,高阶函数就是传入一个函数,返回一个函数。

说起来这篇文章并没有讲到这样的例子呀~

关于平时写的时候抽象不到这个层次的问题,实际上,这种方法很多时候是"被迫"要去做的,你比如说函数防抖:

document.getElementById('test').onmouseover = fn

每当 mouseover 的时候,就会去执行 fn 函数,如果我们要做防抖,我们可以直接在 fn 函数内部去做,但这样就会跟 fn 的代码连在一起,如果我们要给多个函数都做防抖,岂不是每次都要写一遍,所以我们才会单独抽离写一个 debounce 函数:

var debounceFn = debounce(fn);
document.getElementById('test').onmouseover = debounceFn

你看赋给 onmouserover 的值必须要是一个函数,所以你写 debounce 函数的时候,不就是要传入一个函数,返回另一个函数吗?

关于你写的这个 cb 函数,我最一开始以为是 underscore 中的 cb 函数,后来觉得这个有点像 bind 函数的模拟实现:

fucntion bind(fn, context){
         return function(){
               return fn.apply(context,arguments);
         }
}

bind 函数其实也是同样的道理,我们只是想将一个函数的 this 指向一个固定的 context,如果我们直接使用 fn.call(context) ,就执行了 fn 函数,其实我们现在还并不想执行这个函数,所以为了不让他立刻执行,就可以返回一个函数,里面”包裹“着执行 fn 函数的代码。

嗯,说了这么多,还是要多看多思考……

最后,

记得早点睡觉哈~ 😀

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024 1

@iiicon 哈哈,我竟然没有发现……😂 这个 cb 函数是我当时简写 underscore 的 cb 函数得来的……现在看来,写法上有点莫名其妙,给你造成了困扰,我很抱歉,完整的 cb 函数还要参考 underscore 系列之内部函数 cb 和 optimizeCb

如果我现在写的话,应该是写成:

function cb(func, context) {
       if (context === void 0) return func;
       return function() {
           return func.apply(context, arguments);
      };
}

我还是修改一下吧~

from blog.

Tan90Qian avatar Tan90Qian commented on September 21, 2024 1

@mqyqingfeng 在具有fromIndex参数的实现版本里,没有考虑传入的参数为NaN的问题,因为typeof NaN为“number”,也会走进if语句的代码体内,导致参数被污染,而原生的indexOf没有这个问题[1,2,3,1].lastIndexOf(1,NaN) //0以及[1,2,3,1].indexOf(1,NaN) // 0,虽然不知道为什么都返回了0。。。

from blog.

FrontToEnd avatar FrontToEnd commented on September 21, 2024

厉害了 大神

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024

@FrontToEnd []~( ̄▽ ̄)~*

from blog.

xiaobinwu avatar xiaobinwu commented on September 21, 2024

方法都好妙

from blog.

HowardTangHw avatar HowardTangHw commented on September 21, 2024

🤒 之前看过loadsh的源码解读,感觉实现的方式都是差不多的~

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024

@HowardTangHw 确实如此,毕竟两者“本是同根生”~

from blog.

bailinlin avatar bailinlin commented on September 21, 2024

好了,看了你的专题,我要开始读源码了

from blog.

GopherJ avatar GopherJ commented on September 21, 2024
function findLastIndex(array, predicate, context) {
    var length = array.length;
    for (var i = length; i >= 0; i--) {
        if (predicate.call(context, array[i], i, array)) return i;
    }
    return -1;
}

这里i的初始笔误了么

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024

@GopherJ 这是一个倒序循环,所以 i 是从 length 开始,i 的值依此递减

from blog.

GopherJ avatar GopherJ commented on September 21, 2024

@mqyqingfeng 是我糊涂了么233?还是没懂,有 arr[arr.length] 这个项么?

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024

@GopherJ 哈哈,尴尬了😂 感谢指出~

from blog.

GopherJ avatar GopherJ commented on September 21, 2024

@mqyqingfeng 哈哈我就说肯定笔误了。感谢分享啊!写的非常不错,有些地方我估计还得来来回回看几次,期待新的文章!

from blog.

dowinweb avatar dowinweb commented on September 21, 2024

楼主能不能解释下为什么参数中经常会写context,而实际并未传入呀,基本上都是undefined

from blog.

dowinweb avatar dowinweb commented on September 21, 2024

@mqyqingfeng 嗯嗯,学习了,谢谢

from blog.

Qinghuanhehuan avatar Qinghuanhehuan commented on September 21, 2024

倒序查找下标函数里,“item == 1”的返回值不应该是3吗?
console.log(findLastIndex([1, 2, 3, 4], function(item, index, array){
if (item == 1) return true;
})) // 0

from blog.

delayk avatar delayk commented on September 21, 2024

@Qinghuanhehuan 你这个逻辑想错了呀。给你一个数组[1,2,3,4],让你找出最后一个1出现的index,你说这个index应该是多少?明显应该是0嘛。。

from blog.

HowardTangHw avatar HowardTangHw commented on September 21, 2024

@Qinghuanhehuan 虽然是从后面找,可是下标还是从前面开始的,无论从前面开始找,还是后面开始找,最终返回的是元素在数组下的下标,而不是第几位

from blog.

delayk avatar delayk commented on September 21, 2024

@Qinghuanhehuan 你只是倒序查找这个数组,并不是把数组倒序,然后正向查找

from blog.

Qinghuanhehuan avatar Qinghuanhehuan commented on September 21, 2024

@delayk @HowardTangHw 嗯嗯,懂了,谢谢!

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024

@delayk @HowardTangHw 感谢回答哈~ @Qinghuanhehuan ,其实你可以这样想哈,我们倒序查找也是为了找出该元素的下标,然后通过 arr[下标值] 来获取元素,如果 [1, 2, 3, 4] 查找 item === 1,返回值是 3 的话,我们通过下标获取该元素,arr[3] 不就取成了 4 吗?

from blog.

iiicon avatar iiicon commented on September 21, 2024
function cb(fn, context) {
    return function(obj) {
        return fn ? fn.call(context, obj) : obj;
    }
}

传入一个函数,返回另一个函数,这属于函数柯里化吗?
平时写的时候总是抽象不到这个层面。

from blog.

zjp6049 avatar zjp6049 commented on September 21, 2024

@iiicon 所以我也感觉写的so nb,脑洞太大

from blog.

iiicon avatar iiicon commented on September 21, 2024

@mqyqingfeng 我其实是拷贝的你的 sortedIndex 第二版的 iteratee 函数,我感觉和 bind 关系不大,如果不抽象一般就 iteratee(array[mid], fn, context), 我一般就这样

还有就是在南方这边工作就是要中午睡一大觉,晚上不熬个夜感觉贼浪费,不过你说的很对,得爱惜自己的身体
古耐~~

from blog.

mqyqingfeng avatar mqyqingfeng commented on September 21, 2024

@Tan90Qian 感谢指出~ 确实有这个问题~

此外,关于 [1,2,3,1].lastIndexOf(1,NaN) 结果为 0,是因为 fromIndex 如果为 NaN , fromIndex 的值相当于被设置为 0,这点在 MDN 的 lastIndexOf 的模拟实现中可以看出:

default

from blog.

habc0807 avatar habc0807 commented on September 21, 2024

最近我在手动实现数组的常用方法,同事推荐看你的这篇文章,受益匪浅。

from blog.

Dannyzn avatar Dannyzn commented on September 21, 2024
indexOf ---->. var index = dir > 0 ? 0 : length - 1;
for (; index >= 0 && index < length; index += dir) 
不管是正序遍历还是逆序遍历都是满足 于这个 循环遍历的条件
 

from blog.

Dannyzn avatar Dannyzn commented on September 21, 2024
学习笔记分析
function createIndexOf(dir) {
  return function(array, item, idx) {
    var length = array.length;

    var i = 0;
 
    // [0,1,1,2,4]
    // idx 正数  0, 1, 2, 3, 4
    // idx 负数  -5,-4,-3,-2,-1
    
    // idx 的格式判断
    // dir > 0 ===>  我们需要的是 i
    // dir < 0 ===>  我们需要的是 length
    // 和下面的for 循环 成为 一一对应的 关系

    //   dir > 0  从前向后查找  length 此时是数组的长度(需要遍历的次数)
    //  i 是指 从数组 array[i] 开始遍历 
    //  在 dir > 0  ===>  idx >= 0  i = idx
    //  在 dir > 0  ===>  idx <  0  i = Math.max(length + idx, 0)

    //   dir < 0  从后向前查找     i 此时是初始值  
    //  length  是指这当前数组可遍历的次数(长度) 
    //  dir < 0  ===> idx >= 0   length  Math.min(idx + 1, length)
    //  dir < 0  ===> idx < 0    length  idx + length + 1;
    if (typeof idx == 'number') {
      if(dir > 0) {
        // 这里懵了 会,确实不应该
        i = idx >= 0 ? idx : Math.max(length + idx, 0)
      } else {
        length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
      }
    }

    // dir 1 和 -1 => 正向查找 he 逆向查找 

    for(idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir ) {
      if (array[idx] === item) return idx;
    }

    return -1;
  }
}

from blog.

lqPrototype avatar lqPrototype commented on September 21, 2024

字符串的indexOf 有很大的学问,楼主可以看看。

from blog.

yinju123 avatar yinju123 commented on September 21, 2024

可能是我技术的问题,我感觉稍微有点乱。typeof idx == "number这个步骤只对后面的for循环有用吧,我觉得可以把它跟for循环写在一起。然后我有个问题sortedIndex && idx && length其中的 idx是什么意思,而且还是else if判断的,那么传入idx时,sortedIndex是无效的

if (typeof idx == "number") {
            if (dir > 0) {
                i = idx >= 0 ? idx : Math.max(length + idx, 0);
            }
            else {
                length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
            }
        }
        else if (sortedIndex && idx && length) {
            idx = sortedIndex(array, item);
            // 如果该插入的位置的值正好等于元素的值,说明是第一个符合要求的值
            return array[idx] === item ? idx : -1;
        }

        // 判断是否是 NaN
        if (item !== item) {
            idx = predicate(array.slice(i, length), isNaN)
            return idx >= 0 ? idx + i: -1;
        }

        for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
            if (array[idx] === item) return idx;
        }
        return -1;

from blog.

dsphoebe avatar dsphoebe commented on September 21, 2024

@yinju123 https://github.com/jashkenas/underscore/blob/58df1085cdb05cb0888719c5fe5493948604ab69/test/arrays.js#L351-L353 underscore 的测试案例里面可以看出来,idx 是在非数字的情况下,才会触发 sortedIndex 的执行。

from blog.

zlh-GitHub avatar zlh-GitHub commented on September 21, 2024

感觉把idx 改为 fromIndexlength 改为 end 会比较好理解,然后逆向查找的判断里面 end 的计算可以不用再 +1,相当于计算查找范围的最后的位置,这样在 for 循环里的三元运算中的 end 也不用再减了,最后把 i < end - 1 改为 i <= end 就行

const createIndexOfFinder = dir => {
  return (arr, item, fromIndex) => {
    let end = arr.length;
    let i = 0;
    if (typeof fromIndex === 'number') {
      if (dir > 0) { // 正向查找
        ......
      } else { // 逆向查找
        end = fromIndex >= 0 ? Math.min(fromIndex, end) : fromIndex + end;
      }
    }
    for (i = dir > 0 ? i : end; i >= 0 && i <= end; i += dir) {
      ......
    }
    return -1;
  }
}

from blog.

bobo-only-cv avatar bobo-only-cv commented on September 21, 2024

针对于lastIndexOf,关于NaN的查找哪里有点bug
根据‘’其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。‘’
这句话
console.log(lastIndexOf([NaN,1,2],NaN,-5)) 应该返回-1的;
实际调用文中的方法会返回0
原因是因为slice去截取的时候length作为负数也是会从数组末尾向前的偏移

可以增加一条判断
if (typeof idx == "number") { if (dir > 0) { i = idx >= 0 ? idx : Math.max(length + idx, 0); } else { //此处可以增加一条判断 if(Math.abs(idx)>length) return -1; length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; } }

不知道说的对不对

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.