资讯专栏INFORMATION COLUMN

【坑】JavaScript 对象方法执行的上下文

Lsnsh / 1296人阅读

摘要:解决办法知道了原因,很明显解决办法就是为要使用的方法绑定上下文。需要特别注意的是,只有在点操作之后马上执行,才会有上下文,给人造成是调用了对象里面的方法的假象如果如上文描述那样进行了赋值操作,则在执行的时候就不会有什么上下文了。

这是一个由于对 JavaScript 函数上下文理解不够深入而遇到的坑。

背景

在表单验证中,利用高阶函数,抽象一个可以返回特定验证逻辑的验证函数:

// 正则匹配
const getParser = (type) => {
  switch (type) {
    case "chname":
      return /^([u4e00-u9fa5]+|([a-zA-Z]+s?)+)$/g;
    case "email":
      return /^[a-z0-9]+([._-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
    case "phone":
      return /^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])d{8}$/;
    case "password":
      return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])[a-zA-Z0-9!@#$%^&*()]{8,16}$/;
    default:
      return () => false;
  }
};
 
const getMatch = (value) => `${value}`.match;
const isValid = (value, type) => getMatch(value)(getParser(type));

isValid("12345678901", "phone");
问题

执行 getMatch(value)(getParser(type)) 的时候,无法完成验证,程序陷入停止,无法往下执行。

原因

在执行形如 var a = obj.func 的代码的时候,我们以为得到的变量 a 的上下文是 obj,然后执行 a() 的时候,就会跟执行 obj.func() 一样;然而实际上,得到的 a 只是一个单纯的函数,并不会自动绑定 obj 为上下文。

再来看上面的代码的最后一句:

const isValid = (value, type) => getMatch(value)(getParser(type));

通过 getMatch(value) 得到一个 match 方法,但是与预期不同,此时得到的 match 方法的上下文并不是 value,因而会执行失败。

解决办法

知道了原因,很明显解决办法就是为要使用的 match 方法绑定上下文。在 Javascript 中,有很多种方法可以实现:

/// bind
const getMatch = (value) => `${value}`.match.bind(value);
const isValid = (value, type) => getMatch(value)(getParser(type));

/// call
const getMatch = (value) => `${value}`.match;
const isValid = (value, type) => getMatch(value).call(value, getParser(type));

/// apply
const getMatch = (value) => `${value}`.match;
const isValid = (value, type) => getMatch(value).apply(value, [getParser(type)]);
结论

JavaScript 的面向对象特性,比想象中还要弱一些。根本没有什么 “类方法” ,所有形如 obj.func1() 的点操作方法执行,只不过是将 obj 作为上下文去执行 func1 函数罢了。需要特别注意的是,只有在点操作之后马上执行,才会有上下文,给人造成是 “调用了对象 obj 里面的 func1 方法” 的假象;如果如上文描述那样进行了赋值操作 func2 = obj.func1,则在执行 func2 的时候就不会有什么上下文了。

参考文章

Javascript 中的上下文,我的认识的三个阶段
Javascript中的Bind,Call和Apply

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

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

相关文章

  • JavaScript那些

    摘要:序列化为字符串之后它的各个属性已经被解除了引用,重新相当于创建了一个新的对象。类似于的,的命令行终端。基本思路函数的使用以及协议。 多行注释的陷阱 由于正则表达式字面量的存在,多行注释可能会产生陷阱,例如以下程序将抛出错误: /* var a = /h*/.test(hello); */ 正则结束前的那个星号将被解析为注释结束符,从而.被认为是不合法的.所以尽量避免使用多行注释 整型 ...

    ivyzhang 评论0 收藏0
  • 透彻研究Javascript类型转换

    摘要:注释空数组空对象转换为布尔型也是坑。系统会在自动类型转换的时候调用他们,所以我们通常不需要手动调用他们。严格相等不存在类型转换,对于类型不同的两个值直接返回。 Javascript 中有5种基本类型(不包括 symbol),以及对象类型,他们在不同的运算中会被系统转化为不同是类型,当然我们也可以手动转化其类型。 Javascript 类型转换中的坑极多,就连 Douglas Crock...

    dailybird 评论0 收藏0
  • javascript高级程序设计》函数调用模式 & this深度理解

    在上一篇文章(《javascript高级程序设计》笔记:Function类型)中稍微提及了一下函数对象的属性—this,在这篇文章中有深入的说明: 函数的三种简单调用模式 1 函数模式 定义的函数,如果单独调用,不将其与任何对象关联,那么就是函数调用模式 function fn(num1, num2) { console.log(this); } // 直接在全局调用 fn();// w...

    wyk1184 评论0 收藏0
  • JavaScript作用域学习笔记

    摘要:我们再来看一下第一段代码小红小黑脚本出错脚本出错在这段代码中变量与函数,都拥有局部作用域。作用域链的最前端,始终都是当前执行代码所在的作用域的变量对象。 个人博客原址 无论什么语言中,作用域都是一个十分重要的概念,在JavaScript中也不例外,作用域定义了变量或者函数有权访问的范围,决定了它们各自的行为。要理解JavaScript中的作用域首先就要知道:在let出现之前,JS中变...

    jerryloveemily 评论0 收藏0
  • JQuery,说说哪些大家都踩过

    摘要:回调在请求成功或失败都会触发。为避免多次执行,请先做事件解绑再重新绑定。避免响应多次执行错误使用指示符坑人指数指示符存在于一定的上下文中的,当上下文变化时指向不同的对象。 1 乱用选择器 坑人指数:200 JQuery选择器调用代价很大,反复调用效率更低。应采用缓存对象的方法或采用链式调用的方式。 //错误的写法 $(#button).click(function(){ $(#...

    habren 评论0 收藏0

发表评论

0条评论

Lsnsh

|高级讲师

TA的文章

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