资讯专栏INFORMATION COLUMN

Javascript中函数作为对象的魅力

morgan / 2080人阅读

摘要:赋予了函数非常多的特性,其中最重要的特性之一就是将函数作为第一型的对象。那就意味着在中函数可以有属性,可以有方法,可以享有所有对象所拥有的特性。参考资料忍者秘籍关于函数我之前还写过一篇中高阶函数的魅力有兴趣的话可以看一看。

Javascript赋予了函数非常多的特性,其中最重要的特性之一就是将函数作为第一型的对象。那就意味着在javascript函数可以有属性,可以有方法, 可以享有所有对象所拥有的特性。并且最重要的,她还可以直接被调用

我们简单的试验一下就可以发现

// 简单实验 函数作为对象的存在
let fn = function () {}
fn.prop = "fnProp"
console.log(fn.prop) // fnProp

为函数添加属性的这个特性我觉的大家在平时的开发中基本没什么尝试或者是使用过,但是在一些JS库或者是事件回掉管理中都能发挥出很大的用处。下面一起来看几个例子。

函数缓存

在某有一些的情况下我们可以要存储一组相关但是相互又独立的函数。这个需求看起来很easy,实现起来也不复杂。最显而易见的做法是使用一个数组来保存所有的函数,
这样不是不可以,但是显然这种做法不是最好的。下面通过为函数属性我们呢来实现这个我们的目的

// 1:函数缓存示例
let store = {
  nextId: 1, // id
  cache: {}, // 缓存
  add (fn) {
    // 如果函数中没有id属性那么就缓存
    if (!fn.id) {
      console.log(`begin add func ${fn.name}`)
      fn.id = store.nextId ++
      // 设置完缓存之后返回true
      return !!(store.cache[fn.id] = fn)
    } else {
      console.log(`${fn.name} is already in cache`)
    }
  }
}
function storeCache() {}
store.add(storeCache) // begin add func storeCache
store.add(storeCache) // storeCache is already in cache

上面的这一段代码逻辑清晰,store对象用来管理我们的缓存,cache属性用来存储函数,nextId属性用来保存当前的缓存Id,add()方法用来设置存储,先来判断当前函数是否已经在缓存中然后再去设置缓存,这样就能限制函数的重复添加,最后返回true

!!构造是一种可以将任意Javascript表达式转化为其等效布尔值的简单方式。
缓存记忆函数

这种函数可以记住之前已经计算过的结果,避免了不必要的计算,这显然是能够提升代码性能的。

在举例之前我们先来看看这种方式的优缺点
优点

缓存了之前的结果,最终用户享有性能优势

实际上是发生在幕后,操作无感

缺点

内存的牺牲这是肯定的

打破了存粹性(一个函数或者方法应该只做好一件事)

如果方法中有算法,那么很难测量这个算法的性能

了解了优缺点我们来看一个简单的计算素数的例子(不是很严谨)

// 2: 缓存记忆函数
function isPrime (value) {
  if (!isPrime.anwers) isPrime.anwers = {}
  // 先从缓存里面取
  if (isPrime.anwers[value] != null ) {
    return isPrime.anwers[value]
  }
  // 开始进行判断和计算
  let prime = value != 1
  for (let index = 2; index < value; index++) {
    if (value % index == 0) {
      prime = false
      break;
    } 
  }
  // 保存计算出来的值
  return isPrime.anwers[value] = prime
}

console.log(isPrime(5))
console.log(`从函数记忆中直接读取${isPrime.anwers[5]}`)

这里呢 好处是特别明显的我们再次的取用isPrime.anwers[5]的时候不需要经过任何的计算,但是大型的计算要主要内存的使用

缓存记忆DOM元素

通过元素的标签查询DOM的操作的的代价是昂贵的,各位前端大佬肯定都很清楚。我们下面使用缓存记忆的方式来进行这个操作

// 3:缓存记忆DOM元素
function getElements (name) {
  if (!getElements.cache) getElements.cache = {}
  return getElements.cache[name] = getElements.cache[name] || document.getElementsByTagName(name);
}
console.log(getElements("div")) // HTMLCollection
console.log(getElements.cache["div"]) // HTMLCollection

这个函数和上面的缓存使用的同一个手法,而且这简单的4句代码能为我们的性能带来大幅度的提升。这也算是一种超能力吧。函数的很多特性都和其上下文有关,接下来我们研究一个和上下文又换的例子。

伪造数组方法(上下文相关)

在一些情况下我们想创建一个包含一组数据的对象,但是这个数据包含很多的状态,比如和集合项有关的元数据那么我们用数组来存就不太合适了。那么这里我们就用对象的方式来假扮数组。通过改变上下文来完成一些“不法的行为”

// 4:伪造数组方法
// 
// 
let elems = {
  length: 0, //为了保存个数
  add (elem) {
    Array.prototype.push.call(this, elem)
  },
  gather (id) {
    this.add(document.getElementById(id))
  }
}
elems.gather("add")
elems.gather("remove")
console.log(elems[0]); // 
console.log(elems[1]); // 
console.log(elems.length); // 2
console.log(elems);
/**
  0: input#add
  1: input#remove
  add: ƒ add(elem)
  gather: ƒ gather(id)
  length: 2
 */

在我还对JS懵懵懂懂的时候看到这样的操作被秀了一脸,简直是刺激了我幼小的心灵。

我们在add函数中实现了把元素添加到了集合中,而且Array又正好提供push方法, 不用白不用。这种操作也是直白的展示了函数上下文的超强特性。

总结

Javascript强大的灵活性, 也带来更多的可能性。 路漫漫其修远兮,吾将上下而求索。

参考资料: 《JavaScript忍者秘籍》

关于函数我之前还写过一篇JavaScript中高阶函数的魅力, 有兴趣的话可以看一看。

代码地址

原文地址 如果觉得有帮助的得话给个⭐吧

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103365.html

相关文章

  • JavaScript高阶函数魅力

    摘要:上传进度下面通过高阶函数的方式我们来实现函数节流节流函数计时器是否是第一次调用首次调用直接放行存在计时器就拦截设置使用节流分时函数节流函数为我们提供了一种限制函数被频繁调用的解决方案。 高阶函数是指至少满足下列条件之一的函数 1:函数可以作为参数被传递 2:函数可以作为返回值输出 JavaScript语言中的函数显然的是满足了高阶函数的条件,下面我们一起来探寻JavaScript种高阶...

    Tony_Zby 评论0 收藏0
  • 【阅读笔记】javascript 语言精粹

    摘要:前言由于最近的项目用到了一些的代码,所以我带着好奇心,认真阅读了这本书,粗略地了解语言的基本结构和特性,对于一些不熟悉的新概念,以记录的形式加强印象,也是对学习的反思总结。 前言 由于最近的项目用到了一些js的代码,所以我带着好奇心,认真阅读了这本书,粗略地了解js语言的基本结构和特性,对于一些不熟悉的新概念,以记录的形式加强印象,也是对学习的反思总结。 一、字面量(literals...

    tangr206 评论0 收藏0
  • 函数式编程之组合

    摘要:在函数式编程的组合中,我们是从右到左执行的,上述的例子中我们借助函数实现组合,当然,我们也可以用自己的方式实现。小结函数式编程随着多核的发展,开始再次出现在我们的视野中,有时候也会担心过于吹捧函数式,反而落入俗套。 程序的本质是什么?数据结构+算法!!!我想这也是很多程序员给出的答案,我自己也认可这一观点,当我们了解了某一门编程语之后,接下来我们面对的往往是数据结构和算法的学习。而现在...

    Jinkey 评论0 收藏0
  • 什么是 JAVASCRIPT

    摘要:,微软发布,同时发布了,该语言模仿同年发布的。,公司在浏览器对抗中没落,将提交给国际标准化组织,希望能够成为国际标准,以此抵抗微软。同时将标准的设想定名为和两类。,尤雨溪发布项目。,正式发布,并且更名为。,发布,模块系统得到广泛的使用。 前言 作为程序员,技术的落实与巩固是必要的,因此想到写个系列,名为 why what or how 每篇文章试图解释清楚一个问题。 这次的 why w...

    ephererid 评论0 收藏0
  • javascript 函数式编程思想

    摘要:今天这篇文章主要介绍函数式编程的思想。函数式编程通过最小化变化使得代码更易理解。在函数式编程里面,组合是一个非常非常非常重要的思想。可以看到函数式编程在开发中具有声明模式。而函数式编程旨在尽可能的提高代码的无状态性和不变性。 最开始接触函数式编程的时候是在小米工作的时候,那个时候看老大以前写的代码各种 compose,然后一些 ramda 的一些工具函数,看着很吃力,然后极力吐槽函数式...

    YPHP 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<