Java实现手写功能_前端手写代码原理实现

前言

现在的前端门槛越来越高,不再是只会写写页面那么简单。模块化、自动化、跨端开发等逐渐成为要求,但是这些都需要建立在我们牢固的基础之上。不管框架和模式怎么变,把基础原理打牢才能快速适应市场的变化。下面介绍一些常用的源码实现:

call实现

bind实现

new实现

instanceof实现

Object.create实现

深拷贝实现

发布订阅模式

call

call用于改变函数this指向,并执行函数

一般情况,谁调用函数,函数的this就指向谁。利用这一特点,将函数作为对象的属性,由对象进行调用,即可改变函数this指向,这种被称为隐式绑定。apply实现同理,只需改变入参形式。

let obj = {

name: 'JoJo'

}

function foo(){

console.log(this.name)

}

obj.fn = foo

obj.fn() // log: JOJO

实现

Function.prototype.mycall = function () {

if(typeof this !== 'function'){

throw 'caller must be a function'

}

let othis = arguments[0] || window

othis._fn = this

let arg = [...arguments].slice(1)

let res = othis._fn(...arg)

Reflect.deleteProperty(othis, '_fn') //删除_fn属性

return res

}

使用

let obj = {

name: 'JoJo'

}

function foo(){

console.log(this.name)

}

foo.mycall(obj) // JoJo

bind

bind用于改变函数this指向,并返回一个函数

注意点:

作为构造函数调用的this指向

维护原型链

Function.prototype.mybind = function (oThis) {

if(typeof this != 'function'){

throw 'caller must be a function'

}

let fThis = this

//Array.prototype.slice.call 将类数组转为数组

let arg = Array.prototype.slice.call(arguments,1)

let NOP = function(){}

let fBound = function(){

let arg_ = Array.prototype.slice.call(arguments)

// new 绑定等级高于显式绑定

// 作为构造函数调用时,保留指向不做修改

// 使用 instanceof 判断是否为构造函数调用

return fThis.apply(this instanceof fBound ? this : oThis, arg.concat(arg_))

}

// 维护原型

if(this.prototype){

NOP.prototype = this.prototype

}

fBound.prototype = new NOP()

return fBound

}

使用

let obj = {

msg: 'JoJo'

}

function foo(msg){

console.log(msg + '' + this.msg)

}

let f = foo.mybind(obj)

f('hello') // hello JoJo

new

new使用构造函数创建实例对象,为实例对象添加this属性和方法

new的过程:

创建新对象

新对象__proto__指向构造函数原型

新对象添加属性方法(this指向)

返回this指向的新对象

function new_(){

let fn = Array.prototype.shift.call(arguments)

if(typeof fn != 'function'){

throw fn + ' is not a constructor'

}

let obj = {}

obj.__proto__ = fn.prototype

let res = fn.apply(obj, arguments)

return typeof res === 'object' ? res : obj

}

instanceof

instanceof 判断左边的原型是否存在于右边的原型链中。

实现思路:逐层往上查找原型,如果最终的原型为null时,证明不存在原型链中,否则存在。

function instanceof_(left, right){

left = left.__proto__

while(left !== right.prototype){

left = left.__proto__ // 查找原型,再次while判断

if(left === null){

return false

}

}

return true

}

Object.create

Object.create创建一个新对象,使用现有的对象来提供新创建的对象的__proto__,第二个可选参数为属性描述对象

function objectCreate_(proto, propertiesObject = {}){

if(typeof proto !== 'object' || typeof proto !== 'function' || proto !== null){

throw('Object prototype may only be an Object or null:'+proto)

}

let res = {}

res.__proto__ = proto

Object.defineProperties(res, propertiesObject)

return res

}

深拷贝

深拷贝为对象创建一个相同的副本,两者的引用地址不相同。当你希望使用一个对象,但又不想修改原对象时,深拷贝是一个很好的选择。这里实现一个基础版本,只对对象和数组做深拷贝。

实现思路:遍历对象,引用类型使用递归继续拷贝,基本类型直接赋值

function deepClone(origin) {

let toStr = Object.prototype.toString

let isInvalid = toStr.call(origin) !== '[object Object]' && toStr.call(origin) !== '[object Array]'

if (isInvalid) {

return origin

}

let target = toStr.call(origin) === '[object Object]' ? {} : []

for (const key in origin) {

if (origin.hasOwnProperty(key)) {

const item = origin[key];

if (typeof item === 'object' && item !== null) {

target[key] = deepClone(item)

} else {

target[key] = item

}

}

}

return target

}

发布订阅模式

发布订阅模式在实际开发中可以实现模块间的完全解耦,模块只需要关注事件的注册和触发。

发布订阅模式实现EventBus:

class EventBus{

constructor(){

this.task = {}

}

on(name, cb){

if(!this.task[name]){

this.task[name] = []

}

typeof cb === 'function' && this.task[name].push(cb)

}

emit(name, ...arg){

let taskQueen = this.task[name]

if(taskQueen && taskQueen.length > 0){

taskQueen.forEach(cb=>{

cb(...arg)

})

}

}

off(name, cb){

let taskQueen = this.task[name]

if(taskQueen && taskQueen.length > 0){

let index = taskQueen.indexOf(cb)

index != -1 && taskQueen.splice(index, 1)

}

}

once(name, cb){

function callback(...arg){

this.off(name, cb)

cb(...arg)

}

typeof cb === 'function' && this.on(name, callback)

}

}

使用

let bus = new EventBus()

bus.on('add', function(a,b){

console.log(a+b)

})

bus.emit('add', 10, 20) //30

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前 言 1 1 概 述 2 1.1 选题背景 2 1.2 组织结构 2 2 所用相关技术和方法 3 2.1 工作流 3 2.1.1 什么叫工作流 3 2.1.2 工作流发展 3 2.1.3 工作流的优点 3 2.2 MVC工作模式 4 2.2.1 MVC设计思想 4 2.2.2 MVC的具体实现 5 2.2.3 MVC的不足 6 2.3 JSP技术介绍 6 2.3.1 JSP的运行原理 7 2.3.2 JSP的生命周期 8 2.3.3 Servlet和JavaBean技术介绍 8 2.3.4 Java 虚拟机 9 2.3.5 JSP访问SQL Server 2000数据库 9 2.4 数据库后台环境配置 10 2.5 系统开发工具简介 10 2.5.1 Dreamweaver 10 2.5.2 MyEclipse 10 2.5.3 Tomcat 11 2.5.4 SQL Server2000 11 2.5.5 chs_sql2ksp3 12 3 系统需求分析 13 3.1 系统功能分析 13 3.2 系统性能分析 13 3.3 系统方案的确定和评价 13 4 系统总体设计 15 4.1 系统层次模块图 15 4.1.1 营业厅模块 15 4.1.2 收费管理模块 16 4.2 系统数据流程图 16 4.3 数据表设计 18 5 详细设计及编码 21 5.1 编写JAVABEAN 21 5.2 营业厅实现函数 21 5.3 收费厅主要的实现函数 22 5.4 JAVABEAN主要实现模块 22 5.4.1 中文字符格式的转换模块(Stringto.java) 22 5.4.2 自动生成验证码(Ran.java) 22 5.4.3 数据库的连接(ConnectionFactory.java) 23 5.4.4 数据库连接的关闭(DatabaseUtils.java)--只提供接口 23 5.4.5 密码修改模块(Common_fuction.java) 24 5.4.6 时间格式转换(timeBean.java) 24 5.4.7 数据统计(counthander.java) 25 5.4.8 营业厅的接口(luruaction.java) 27 5.4.9 营业厅的主要函数实现(luruhander.java) 28 5.4.10 收费厅的主要函数接口 32 5.5 管理员登陆模块 33 5.5.1 管理员登录 33 5.6 营业厅管理模块 36 5.6.1 Left.jsp页面 36 5.6.2 Work.jsp 40 5.6.3 customerlistinfo.jsp 41 5.6.4 allinfo.jsp 41 5.7 收费厅管理模块 42 5.7.1 Left.jsp 42 5.7.2 Work.jsp 43 5.7.3 Customerlistinfo.jsp 43 5.7.4 gongdan.jsp 43 6 系统测试与维护 45 6.1 测试目的 45 6.2 测试环境 45 6.3 系统测试 45 6.4 系统维护 45 7 开发难点与技术 46 7.1 主要程序实现代码描述 46 7.1.1 验证码的自动生成 46 7.1.2 生成WORD工单 46 7.1.3 以一定的时间刷新页面 47 7.1.4 JSP中文问题的解决 47 7.2 在程序编码过程遇到的主要问题: 48 7.3 代码编写风格 49 7.4 我的不足: 49 结束语 50 致 谢 50

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值