银行java面试题手写代码_面试系列——手写代码实现(一)
前言
本文是面试系列篇的实现篇。笔者整理了面试过程中可能会遇到的手写实现,以及它的原理。这可以帮助面试者在笔试环节获得良好的加分。
其他文章系列,欢迎关注我文末的公众号
正文
apply和call
apply和call的实现中,主要是利用了两个点:
根据传入的thisArgs去创建对象
在新创建的对象上定义当前函数,然后进行调用
apply和call的区别:
apply在指定对象后只接受一个参数
call在指定对象后可以接受多个参数
代码实现如下:
/**
* apply模拟实现
*/
Function.prototype.myApply = function(thisArg, arrArg) {
//#1 类型检测
if (typeof this !== 'function') {
throw new TypeError(`${this}.apply is not a function`);
}
//#2 arrArg和thisArg参数判断
if (arrArg === undefined || arrArg === null) {
arrArg = [];
}
if (thisArg === undefined || thisArg === null) {
thisArg = _self;
}
//#3 创建对象,函数赋值,调用对象方法
const obj = new Object(thisArg);
obj['_fn_'] = this;
var result = obj['_fn_'](...arrArg);
delete obj['_fn_'];
return result;
}
/**
* call模拟实现
*/
Function.prototype.myCall = function(thisArg) {
//#1 类型检测
if (typeof this !== 'function') {
throw new TypeError(`${this}.call is not a function`);
}
//#2 参数调整
const argumentsArr = [];
for (let i = 1; i < arguments.length; i++) {
argumentsArr.push(arguments[i]);
}
if (thisArg === undefined || thisArg === null) {
thisArg = _self;
}
//#3 创建对象,函数赋值,调用对象函数
const obj = new Object(thisArg);
var _fn = '_fn_';
obj[_fn] = this;
var result = obj[_fn](...argumentsArr);
delete obj[_fn];
return result;
}
复制代码
bind和softBind实现
bind和softBind的区别:
bind的绑定对象是固定的,softBind相当于是一种软绑定【如果this为空,或者指向全局对象时,才改变函数的绑定】
bind和apply & call的区别:
bind返回一个函数;apply和call是调用时执行的
代码实现如下:
/**
* bind实现
*/
Function.prototype.myBind = function(obj) {
//#1 类型校验
if (typeof this === 'function') {
throw new TypeError(`${this}.bind is not a function`);
}
//#2 取参
const args = Array.prototype.shift.call(arguments) || [];
const fn = this;
//#3 定义函数,调用apply改变this指向,同时改变新函数的原型
var bindFn = function() {
return this.apply(obj, [].concat(args, arguments));
}
bindFn.prototype = fn.prototype;
return bindFn;
}
/**
* softBind的实现
*/
Function.prototype.softBind = function(obj) {
//#1 类型校验
if (typeof this === 'function') {
throw new TypeError(`${this}.softBind is not a function`);
}
//#2 取参
const args = Array.prototype.shift.call(arguments) || [];
const fn = this;
//#3 定义函数,调用apply,此处注意对this的判断,改变新函数的原型
var softBindFn = function() {
return fn.apply((!this || this === (window || global) ? obj : this), [].concat(args, arguments));
}
softBindFn.prototype = fn.prototype;
return softBindFn;
}
复制代码
new的实现
new实现的过程:
创建一个新的对象
将新对象的隐式引用(proto)指向构造函数的原型
通过apply调用构造函数,给这个对象赋值
最后判断返回的对象是否是一个对象,然后结果
代码实现如下:
/**
* new模拟实现
*/
function myNew() {
//#1 创建一个空对象
let obj = Object.create({});
//#2 取出构造函数
let Constructor = Array.prototype.unshift.call(arguments);
//#3 改变新对象的隐式指向
obj._proto_ = Constructor.prototype;
//#4 调用构造函数,返回结果
ret = Constructor.apply(obj, arguments);
//#5 对结果进行判断
return ret instanceof Object ? ret : obj;
}
复制代码
instanceof的实现
instance的实现:
取出隐式引用(proto),然后和原型进行比较
依次往上循环,直到__proto__为null时
代码实现如下:
/**
* 实现instanceof
*/
function instanceFn(L, R) {
//#1 取出R的原型
const O = R.prototype;
//#2 取L的隐式指向,依次在原型链上判断
L = L._proto_;
while(true) {
if (L === null) {
//#3 当L为空时,返回false
return false;
} else {
//#4 当O与L相等是,说明继承于R
if (O === L) {
return true;
}
L = L._proto_;
}
}
}
复制代码
ES6的extend实现
ES6中的extend实现的原理:
将子构造函数的原型指向父构造函数的实例
然后改变原型中的构造函数(constructor)指向子构造函数
然后将子构造函数的隐式指向(proto)指向父构造函数
代码实现如下:
/**
* extend模拟实现
*/
function _inherits(subType, superType) {
//#1 创建对象,增强对象,指定对象
subType.prototype = Object.create(superType && superType.prototype, {
constructor: {
value: subType,
writable: true,
configurable: true,
enumerable: false
}
});
//#2 给子构造函数的隐式指向父构造函数
if (superType) {
Object.setPrototypeOf ? Object.setPrototypeOf(subType, superType) : subType._proto_ = superType;
}
}
复制代码
深拷贝和浅拷贝的实现
浅拷贝,就是只进行一层拷贝:
把对象的key取出来,然通过hasOwnProperty判断,赋值
深拷贝,就是无限层级的拷贝:
通过Map的形式,解决循环引用,如果对象存在,则直接返回
通过getOwnPropertySymbols的方法,解决Symbol值的拷贝
循环递归,拷贝对象属性
代码实现如下:
/**
* 浅拷贝
*/
function shallowCopy(obj) {
//#1 类型校验
if (obj !== 'object') return obj;
const target = {};
//#2 遍历对象的key
for (let key in obj) {
//#3 判断key是否在对象上
if (obj.hasOwnProperty(key)) {
target[key] === obj[key];
}
}
return target;
}
/**
* 深拷贝
*/
function isObject(obj) {
return typeof obj === 'object' && obj !== null;
}
function deepCopy(source, hash = new WeakMap()) {
//#1 类型校验
if (!isObject(source)) return source;
//#2 解决循环引用
if (hash.get(source)) return hash.get(source);
//#3 创建新对象,存入hash中
const target = Array.isArray(source) ? [] : {};
hash.set(source, target);
//#4 Symbol拷贝
const symbolArr = Object.getOwnPropertySymbols(source);
if (symbolArr.length) {
symbolArr.forEach(key => {
if (isObject(source[key])) {
target[key] = deepCopy(source[key], hash);
} else {
target[key] = source[key]
}
})
}
//#5 遍历对象key值
for (let key in source) {
//#6 判断是否是对象的key
if (source.hasOwnProperty(key)) {
//#7 判断属性类型
if (isObject(source[key])) {
target[key] = deepCopy(source[key], hash);
} else {
target[key] = source[key];
}
}
}
return target;
}
复制代码
防抖和节流的实现
节流:事件在一段时间内只会被触发一次,多次触发,只有一次生效
防抖:在事件触发n秒后再被调用,如果在这n秒内又被触发,则重新计时
代码实现如下:
/**
* 节流
*/
function throttle(fn, delay) {
//#1 定义上次触发时间
let last = 0;
return function() {
//#2 取参
const args = arguments;
const now = +new Date();
//#3 判断是否超过之前的时间
if (now < last + delay) {
last = now;
fn.apply(this, args);
}
};
}
/**
* 防抖
*/
function debounce(fn, delay) {
let timer;
return function(...args) {
//#1 判断定时器是否存在,清除定时器
if (timer) clearTimeout(timer);
//#2 重新调用setTimeout
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
复制代码
Promise的all和race实现
Promise.all:谁跑得慢,以谁为准,如果有一个失败,就返回失败结果
Promise.race:谁跑得快,以谁为准
代码实现如下:
/**
* all模拟实现
*/
Promise1.all = function (promises) {
//#1 计时器 & 结果数组
let count = 0;
const res = [];
//#2 传值函数,将结果放入结果数组
function processData (index, data, resolve) {
res[index] = data;
count++;
if (count === promises.length) {
resolve(res);
}
}
//#3 返回一个Promise
return new Promise((resolve, reject) => {
for (let j = 0; j < promises.length; j++) {
//#4 遍历promises数组,调用每个promise,将结果放入结果数组
promises[j].then(data => {
processData(j, data, resolve);
}, reject);
}
});
}
/**
* race模拟实现
*/
Promise1.race = function (promises) {
//#1 返回一个Promise
return new Promise((resolve, reject) => {
//#2 遍历promises数组,谁先返回,就用谁
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
}
复制代码欢迎关注博主的微信公众号,我们一起做沟通和交流
银行java面试题手写代码_面试系列——手写代码实现(一)相关推荐
- java代码里的JSON格式怎么写好看_谁会不爱让代码骚里骚气的VSCode扩展插件呢?...
点击上方 "Python人工智能技术" 关注,星标或者置顶22点24分准时推送,第一时间送达 来自:公众号 读芯术 | 编辑:真经君 码农真经(ID:coder_experienc ...
- 新网银行java面试题_新网银行面试
有点累了.... 2017年9月13号下午四点半 ,去新网银行面试.这是我第一次参加群面(但当时是两个人一组进行面试,所以我和另外一个哥们一起面对两个面试官回答问题),有点紧张,导致手写代码和回答问题 ...
- java基础试题_java基础测试题_含答案.doc
java基础测试题_含答案 Java基础试题 姓名 一.选择题(每题2分,共30分) 请写出标识符的命名规则描述正确的是[多选]( ABCD ) A.由英文字母.数字._和$组成,长度不限. B.标识 ...
- idea看更改过的代码_就是你把所有代码全写在一个类里的?
来源 | https://urlify.cn/6jQRN3 最近,在对已有项目进行扩展的时候,发现要改动的一个类它长900行,开放了近40个public接口,我流着泪把它给改完了. 为了防止这样的惨剧 ...
- 微信小程序 手写签名_小程序手写签名(wepy)
对于手写签名组件组件晚上有很多种写法,我选择了一种进行了wepy的框架的改造.如果使用wepy框架做手写签名的话可以直接复制下面的代码. 这里需要提醒的是:安卓手机和苹果手机有适配性的问题,苹果手机在 ...
- java词频统计简单带代码_简单的词频统计代码实现(PDF格式)
周末抽空帮同学论文写了一段统计词频的代码,做个简单总结.出于职业病,代码使用Springboot+Maven搭建,面向抽象编程,并通过web请求控制执行. 依赖配置 org.springframewo ...
- vue 手写签名_与众不同的手写签批
随着移动互联网+时代的到来,手机成了我们日常生活中不可缺少的必备用品,它不仅仅是一个通讯工具,更是一台移动电脑.因此越来越多的单位把希望在手机上就能完成业务的处理,但也希望能还原线下办理的效果.因此, ...
- python笔记手写照片_用Python对手写笔记进行压缩与增强
Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 我写了一个程序来清洁手写笔记的扫描图,并同时减少文件大小. 示例输入输出: 左边: 300 DPI, 7. ...
- python写词法分析器_如何用python写一个简单的词法分析器
编译原理老师要求写一个java的词法分析器,想了想决定用python写一个. 目标 能识别出变量,数字,运算符,界符和关键字,用excel表打印出来. 有了目标,想想要怎么实现词法分析器. 1.先进行 ...
最新文章
- canny边缘检测 关于2个阈值参数
- 凭啥Java运行环境称虚拟机 Python只能称解释器
- 如何快速搭建一个简约美观的在线互动教室?
- 深入理解Spring AOP思想
- C++多态案例二-制作饮品
- python安装环境傻瓜式安装_前后端分离——前端开发环境傻瓜式一步到位 nodejs ruby python nginx 安装搭建配置...
- spring aop的两种写法aspect和advisor
- CaseStudy-数据缓存出错
- 遇到的坑_那些年跟团游遇到的坑,花了很多钱才发现自己被坑了
- socket 函数 setsockopt()用法
- 第一章:网络信息安全概述精讲笔记
- Marlin代码分析一些记录
- 嵌入式系统课程大作业设计报告
- 数据可视化之使用Matplotlib绘制甘特图
- java pdf转图片base64,itextpdf 实现html转pdf中中文及图片base64的解决方法
- python直角坐标转极坐标_Python在OpenCV里实现极坐标变换功能
- 4.3.用python解決經典問題:生日悖論, birthday paradox
- 只用3行代码,让Python提速4倍!最强辅助
- 时间序列分析中resample函数
- 表格式计算机教案模板,教案的表格格式_教案的表格模板
热门文章
- js 实现精准定位(使用百度地图API)
- java从服务器读取文件_Java从服务器读取文件并下载到本地
- 二十四、Gtk4-GtkExpression
- Bitmap实现照片墙
- 苏宁易购双十一搞了一场“三无”发布会,却被称赞“干货满满”
- 陌陌开始发力直播,它和那些竞品们有何不同?
- 无法进入netsarang官网
- 图像识别之字符识别方法
- requestPermissions读写手机存储权限_Android 11 开发者常见问题:存储|FAQ?第二期
- 迅雷看看的带宽限制 是不能限制 还是不想限制?