JavaScript基础系列之函数和方法详解_javascript技巧

来源:脚本之家  责任编辑:小易  
目录
一、函数和方法的区别二、如何写好一个函数2.1 命名准确
2.1.1 函数命名
2.1.2 参数命名
2.2 函数注释
2.2.1 参数注释
2.3  函数参数
2.3.1 参数默认值
2.3.2 对象参数
2.3.3 参数数量
2.3.4 参数类型防御
2.4 函数的返回
2.4.1 幂等函数
2.4.2 纯函数
2.4.3 return null
函数和方法的区别总结

一、函数和方法的区别

函数(function):函数是带有名称和参数的 JavaScript 代码段,可以一次定义多次调用。 方法(method):当将函数和对象写在一起时,函数就变成了“方法”,比如当函数赋值给对象的属性时,我们便称其为“方法”。

二、如何写好一个函数

在 JS 中,除了变量,用的最多的应该就是函数了,函数是 Javascript 的第一公民。

2.1 命名准确

2.1.1 函数命名

函数的命名需要明确,语义清晰,简单概括函数的功能。我们不要想着代码简短而缩短函数名称,这并不会提高什么性能或效率,相反,一个函数名称若不够清晰,往往其他人无法理解。

尽量使用动词,比如:getXxxxx、setXxxxx,动词在前面,语义就能更加清晰。

2.1.2 参数命名

强调语义化,参数命名让调用者更清晰的知道该传入什么,对应什么参数。当然,像一些通用命名还是可接受的,像 callback,fn,即使不看注释,往往我也知道这里的参数要做什么,传什么。

2.2 函数注释

/**
 * 时间格式化工具函数
 * 
 * @param { (Date | number) } date - 时间
 * @param { string } unit - 转换格式
 */
export const timeFormat = (date: Date | number | string, unit: string) => {
  if (!date) {
    return ''
  }
  if (typeof date === 'string') return date;
  if (typeof date === 'number') {
    date = new Date(date);
  }
  const year = date.getFullYear();
  const month = date.getMonth() + 1;
  const day = date.getDate();
  const hour = date.getHours();
  const minute = date.getMinutes();
  const second = date.getSeconds();
  if (unit === 'year') return `${year}`;
  if (unit === 'month') return `${year}-${month}`;
  if (unit === 'day') return `${year}-${month}-${day}`;
  if (unit === 'hour') return `${year}-${month}-${day} ${hour}`;
  if (unit === 'minute') return `${year}-${month}-${day} ${hour}:${minute}`;
  if (unit === 'second') return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}

2.2.1 参数注释

/**
 * 时间格式化工具函数
 * 
 * @param { (Date | number) } date - 时间
 * @param { string } unit - 转换格式
 */

@param { type } 参数 - 参数解释:type 表明的是参数的类型,比如 string,number,当有多个参数类型的时候,可以这么来标识 { (string|string[]) },表示这个参数可以是字符串或者字符串数组。

对象属性:需要解释对象的每一个属性

/**
 * 将项目分配给员工的函数
 * 
 * @param {Object} employee - 项目员工
 * @param {string} employee.name - 项目员工的姓名
 * @param {string} employee.department - 项目员工的部门
 */
 Project.prototype.assign = function(employee) {
   // ...
 };

可选参数:

/**
 * 时间格式化工具函数
 * 
 * @param { (Date | number | string) } date - 时间
 * @param { string } [unit] - 转换格式
 */
export const timeFormat = (date: Date | number | string, unit: string) => {
  // ...
}

默认值:

/**
 * 时间格式化工具函数
 * 
 * @param { (Date | number) } date - 时间
 * @param { string } [unit = 'second'] - 转换格式
 */
export const timeFormat = (date: Date | number | string, unit = 'second') => {
  // ...
}

2.3  函数参数

2.3.1 参数默认值

export const timeFormat = (date: Date, unit = 'second') => {
  // ...
}

2.3.2 对象参数

async function printer_proxy_print(
  html_str: string,
  file_path: string,
  device: string | undefined,
  orientation: number,
  printer_mode: string,
  width: number,
  height: number,
  scale: number,
  from: number,
  to: number,
  left_offset: number,
  top_offset: number,
  pdf_tools: string | undefined,
  begin_page = 1,
  end_page = 1,
  repeat_times = 1,
  print_type: string
) {
    // ...
}

可以给参数默认值,这样可以只传前面几个必要的参数,像这样调用。

async function printer_proxy_print(
  html_str: string,
  file_path: string,
  device = 'pc',
  orientation = 'xxx',
  printer_mode = 'xxx',
  width = 123,
  height = 123,
  scale = 123,
  from = 123,
  to = 123,
  left_offset = 123,
  top_offset = 123,
  pdf_tools = 123,
  begin_page = 1,
  end_page = 1,
  repeat_times = 1,
  print_type = 'base64'
) {
    // ...
}

await printer_proxy_print(html_str, file_path);

上面的方法看似可行,实际上,当我中间某个参数不一样的时候,我就需要把这个参数前面的参数都传一遍。这样显然不可行。所以当参数多的时候,我们需要用对象解构的方式传参。

async function printer_proxy_print({
  html_str,
  file_path,
  device = 'pc',
  orientation = 'xxx',
  printer_mode = 'xxx',
  width = 123,
  height = 123,
  scale = 123,
  from = 123,
  to = 123,
  left_offset = 123,
  top_offset = 123,
  pdf_tools = 123,
  begin_page = 1,
  end_page = 1,
  repeat_times = 1,
  print_type = 'base64'
}) {
    // ...
}

await printer_proxy_print({html_str, file_path});

解构的好处便是我可以随便传我想要的某几个参数,而不用在意顺序问题。不过像这么多参数的函数往往存在问题(具体问题具体分析)。也就是下面提到的参数数量问题。

2.3.3 参数数量

一个函数的参数越少越好,最多不应该超过3个,参数多往往意味着关系多,逻辑交叉相对也就多了起来。在进行测试的时候,往往也就很难覆盖到所有条件,出问题概率也就加大了。

参数多的时候,有时候也意味着功能多,就违背了 单一功能 的原则。

2.3.4 参数类型防御

在 TS 开发前,我们不知道用户会传什么东西进来,这时候往往容易产生类型错误,又或者,我们想实现兼容,像前面的 timeFormat 函数,我们希望用户调用的时候,可以是想对 时间对象 格式化,也可以是对 时间戳 格式化,那我们就需要做一个防御处理。

  if (!date) {
    return ''
  }
  if (typeof date === 'string') return date;
  if (typeof date === 'number') {
    date = new Date(date);
  }

不过值得注意的是,即使我们用上了 TS,在大多数情况下,我们确实可以避免参数类型问题,但是这并不绝对,因为我们有时候会直接接受 接口 返回的数据。

我们常说,永远不要相信用户的输入,同样,接口返回的数据我也不信,我们不能保证,后端不会出错,约定好的参数是数组类型,怎么空的时候,你给我个 null 呢?

当然这些情况有时候需要去试错,有时候我们能想到的可能,不要偷懒,给写上类型判断吧。

2.4 函数的返回

2.4.1 幂等函数

什么叫幂等,简单来说,输入什么输出什么是固定的,入参决定了出参,不管调用多少次,只要输入一样,结果应该保持一样。

  function sum(a: number, b: number) {
    return a + b;
  }

幂等函数具有可维护性,相对容易进行单元测试。

2.4.2 纯函数

纯函数在幂等的条件下,还要求没有副作用。

  const dog = {
    name: 'puppy',
    age: 2,
    weight: 30,
  }

  if (!dog.color) {
    console.log('has no color');
  }

  function addColor(dog) {
    dog.color = 'white';
  }

  addColor(dog);
  console.log(dog); // {name: "puppy", age: 2, weight: 30, color: "white"}

可以看到,addColor 函数修改了 dog 对象的属性,也就是产生了副作用。

  function addColor(dog) {
    let copyDog = Object.assign({}, dog);
    copyDog.color = 'white';
    return copyDog;
  }

这样一来,dog 对象的属性就不会修改,addColor 函数是纯函数。

2.4.3 return null

null 在进行处理的时候相对麻烦,需要进行判断,导致了额外的代码,应当返回空对象,或者是空数组,或者抛出异常。

函数和方法的区别

1)函数(function)是一段代码,通过名字来进行调用。它能将一些数据(参数)传递进去进行处理,然后返回一些数据(返回值),也可以没有返回值。

2)方法(method)是通过对象调用的javascript函数。也就是说,方法也是函数,只是比较特殊的函数。他是和一个对象相关联。假设有一个函数是fn,一个对象是obj,那么就可以定义一个method:

obj.method = fn;
obj.method();

3)函数的数据是显式传递

4)方法中的数据是隐式传递的;方法和对象相关。

总结

到此这篇关于JavaScript基础系列之函数和方法的文章就介绍到这了,更多相关JavaScript函数和方法内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网!

您可能感兴趣的文章:js中对函数设置默认参数值的3种方法JavaScript函数的4种调用方法详解js 把字符串当函数执行的方法显示js对象所有属性和方法的函数Javascript 判断是否存在函数的方法js中匿名函数的创建与调用方法分析javascript定义函数的方法js function定义函数的几种不错方法Javascript中eval函数的使用方法与示例JS简单判断函数是否存在的方法

  • 本文相关:
  • webpack4 splitchunks实现代码分隔详解
  • 小程序红包雨的实现示例
  • js组件福利大放送 推荐12款好用的bootstrap组件
  • 详解javascript中arguments对象用途
  • js 文本框里粘贴一个图片url并显示
  • js 图片压缩原理与实现方法详解
  • javascript按顺序加载运行js方法
  • layui问题之模拟select点击事件的实例讲解
  • 在chrome中window.onload事件的一些问题
  • 微信小程序人脸识别功能代码实例
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascriptjavascript技巧js中对函数设置默认参数值的3种方法javascript函数的4种调用方法详解js 把字符串当函数执行的方法显示js对象所有属性和方法的函数javascript 判断是否存在函数的方法js中匿名函数的创建与调用方法分析javascript定义函数的方法js function定义函数的几种不错方法javascript中eval函数的使用方法与示例js简单判断函数是否存在的方法webpack4 splitchunks实现代码分隔详解小程序红包雨的实现示例js组件福利大放送 推荐12款好用的bootstrap组件详解javascript中arguments对象用途js 文本框里粘贴一个图片url并显示js 图片压缩原理与实现方法详解javascript按顺序加载运行js方法layui问题之模拟select点击事件的实例讲解在chrome中window.onload事件的一些问题微信小程序人脸识别功能代码实例js刷新页面方法大全js删除数组里的某个元素方法js中settimeout()的用法详解js页面跳转常用的几种方式js截取字符串常用方法详细整理js数组与字符串的相互转换方法js打开新窗口的2种方式js设置cookie、读取cookie、删除js保留两位小数方法总结js 将json字符串转换为json对象的javascript 另类遍历数组实现代码原生js实现弹幕效果javascript中的getter和setter初识用函数模板,写一个简单高效的 json 查询器javascript原型式继承实现方法将json字符串转换成map对象的方法typescript基础入门教程之三重斜线指令详vs2008中使用javascript调用webservicesbootstrap-treeview实现级联勾选使用jsx 建立组件 parser(解析器)开发的
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved