- undefined 和 undeclared 的区别?
- null 和 undefined 的区别?
- isNaN 和 Number.isNaN 函数的区别?
- 常用正则表达式
- 手写 call、apply 及 bind 函数
时间过得好快,2021 年好像转瞬即逝,再不久,就迎来了金九银十了,不知道准备跳槽的同学们有没有准备好面试呢?
今天趁此整理一下自己之前面试过程中,收集的或者遇到的面试题。
undefined 和 undeclared 的区别?
undefined
:在作用域中声明还没有赋值的变量undeclared
:没有在作用域中声明过的变量
对于undeclared
变量,浏览器会报错误,例如:ReferenceError: b is not defined
null 和 undefined 的区别?
undefined
和 null
都是基本数据类型,undefined
代表的含义是没有定义,null
代表的含义是空对象,一般变量声明没有定义会返回undefined
。
null
在使用typeof
检测的时候会返回object
,我们可以使用typeof
来判断一个变量是否为undefined
,也可以使用===
或者!==
来判断一个变量是否有值,但是不能使用==
来判断。
console.log(null == undefined); //true console.log(null === undefined); //false console.log(typeof null); //object
isNaN 和 Number.isNaN 函数的区别?
isNaN
:接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的值都会返回 true。Number.isNaN
:会首先判断是否为数字,如果是数字再继续判断是否为 NaN。
Number.isNaN
对NaN
的判断最准确。
常用正则表达式
匹配 16 进制颜色值:
const reg = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
匹配日期,如 yyyy-mm-dd 格式:
const dateCheck = = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
匹配 qq 号:
const qqCheck = /^[1-9][0-9]{4,10}$/g;
手机号码:
const phone = /^1[34578]d{9}$/g;
密码强度正则(最少 6 位,包括至少 1 个大写字母,1 个小写字母,1 个数字,1 个特殊字符)
const pPattern = /^.*(?=.{6,})(?=.*d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/;
Email 正则:
const ePattern = /^([A-Za-z0-9_-.])+@([A-Za-z0-9_-.])+.([A-Za-z]{2,4})$/;
身份证号正则:
const cardP = /^[1-9]d{5}(18|19|([23]d))d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)d{3}[0-9Xx]$/;
手写 call、apply 及 bind 函数
call 函数的实现步骤:
- 1.判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
- 2.判断传入上下文对象是否存在,如果不存在,则设置为 window 。
- 3.处理传入的参数,截取第一个参数后的所有参数。
- 4.将函数作为上下文对象的一个属性。
- 5.使用上下文对象来调用这个方法,并保存返回结果。
- 6.删除刚才新增的属性。
- 7.返回结果。
Function.prototype.myCall = function(context) { // 判断调用对象 if (typeof this !== "function") { console.error("type error"); } // 获取参数 let args = [...arguments].slice(1), result = null; // 判断 context 是否传入,如果未传入则设置为 window context = context || window; // 将调用函数设为对象的方法 context.fn = this; // 调用函数 result = context.fn(...args); // 将属性删除 delete context.fn; return result; };
apply 函数的实现步骤:
- 1.判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
- 2.判断传入上下文对象是否存在,如果不存在,则设置为 window 。
- 3.将函数作为上下文对象的一个属性。
- 4.判断参数值是否传入
- 4.使用上下文对象来调用这个方法,并保存返回结果。
- 5.删除刚才新增的属性
- 6.返回结果
Function.prototype.myApply = function(context) { // 判断调用对象是否为函数 if (typeof this !== "function") { throw new TypeError("Error"); } let result = null; // 判断 context 是否存在,如果未传入则为 window context = context || window; // 将函数设为对象的方法 context.fn = this; // 调用方法 if (arguments[1]) { result = context.fn(...arguments[1]); } else { result = context.fn(); } // 将属性删除 delete context.fn; return result; };
bind 函数的实现步骤:
- 1.判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
- 2.保存当前函数的引用,获取其余传入参数值。
- 3.创建一个函数返回
- 4.函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
Function.prototype.myBind = function(context) { // 判断调用对象是否为函数 if (typeof this !== "function") { throw new TypeError("Error"); } // 获取参数 var args = [...arguments].slice(1), fn = this; return function Fn() { // 根据调用方式,传入不同绑定值 return fn.apply( this instanceof Fn ? this : context, args.concat(...arguments) ); }; };
持续更新!