//手写call方法
Function.prototype.mycall = function(content) {
// 1.类型判断
if (typeof this !== 'function') {
throw new Error('not function')
}
// 2. 绑定的上下文处理,没有则默认window
content = content || window
// 3.最重要的一步/ 虚拟出一个fn属性,将函数(this)作为对象的方法,从而this会指向对象(content)
content.fn = this
// 4. 获取参数
let args = Array.prototype.slice.call(arguments, 1)
// 5. 调用函数等到结果
let result = content.fn(...args)
// 6.删除虚拟出来的fn
delete content.fn
// 7. 返回结果
return result
}
// 手写apply 方法
Function.prototype.myapply = function(content) {
if(typeof this !== 'function') throw new Error('not function')
content = content || window
content.fn = this
// 原理同call,只是 参数这里特殊处理, 只取第二个参数
let arg = arguments[1]
let reuslt = content.fn(...arg)
delete content.fn
return reuslt
}
/**
* 手写实现bind方法
* 返回一个新的函数,并将this指向绑定的对象
* 新的函数,可以使用new调用
*/
Function.prototype.bind = function(content) {
if(typeof this !== 'function') throw new Error('not function')
// 保存this(函数)
let self = this
let args = [].slice.call(arguments,1)
// 返回一个新的函数
// 实现bound 可以使用new 调用
let bound = function () {
// 合并参数
let finalArgs = args.concat([...arguments])
// 如果this是bound的实例,即使用 new方法调用bound
if ( this instanceof bound ) {
// 原型继承
if(self.prototype) {
this.prototype = Object.create(self.prototype)
}
// 如果返回的不是引用类型的值,就返回this
let result = this.apply(this, finalArgs)
let isObject = typeof result === 'object' && result !== null
let isFunction = typeof result === 'function'
if(isObject || isFunction) return result
}
// 修改this指向,返回结果
return self.apply(content, finalArgs)
}
return bound
}
/**
* 实现 instanceof 方法
* obj 检测的对象
* func 构造函数
* return boolean
* 判断 func的原型属性(func.prototype)是否在obj的原型链上
*/
function instanceof1 (obj, func) {
let pro = obj.__proto__
let pro2 = func.prototype // 原型对象
while(true) {
if(pro === null) return false
if (pro === pro2) return true
console.log(1)
pro = pro.__proto__ // 依次向上查原型链
}
}
// Object.create(原型对象) 生成实例,继承
function create(proto) {
var F = function(){}
F.prototype = proto
return new F()
}
/**
* 实现一个new操作符
* 1).创建一个新对象
* 2).将新对象继承传入构造器的原型对象
* 3).将this的指向指向新对象,并调用返回结果
* 4).判读结果类型,如果是对象则返回,基本类型则返回obj
*/
function new1(func) {
let obj = {}
// 继承
Object.setPrototypeOf(obj, func.prototype)
// 修改this
let arg = [...arguments].slice(1)
let result = func.call(obj, arg)
if (typeof result == 'object') return reuslt
return obj
}
// 实现promise
/**
* new Promise((resolve, reject)=> {
resove( data )
reject( error )
})
* then( reslove(), rejectd() )
*/
class Promise {
constructor( func ) {
// 声明3个状态 pending/fulfilled/rejected
this.state = 'pending'
// 声明 响应数据和失败原因
this.resdata = null
this.rejectreson = null
// 声明内部的两个方法
let resolve = res => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.resdata = res
}
}
let reject = err=> {
if(this.state === 'pending') {
this.state = 'rejected'
this.rejectreson = err
}
}
//自动执行函数
try {
func(resolve, reject)
}catch (e){
reject(e)
}
}
then (onfulfilled, onrejected) {
swith( this.state ) {
case 'fulfilled':
onfulfilled(this.resdata)
break;
case 'rejected':
onrejected(this.rejectreson)
break;
default:
}
}
}
//浅拷贝 —— 一层拷贝
Object.assign({})
{...obj}
// 深度拷贝
var obj = { name: {age: [12,3]} }
function deepCopy (obj) {
if (typeof obj !== 'object' || obj === null) return obj
let result = Array.isArray(obj) ? [] : {}
for(let key in obj) {
if ( obj.hasOwnProperty(key) ) {
result[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key]
}
}
return result
}
// 使用setTimeout 模拟 setinterval
let timer = function ( cb, i ) {
cb()
setTimeout(timer, i)
}
// 继承1
// 构造器中 使用 superClass.apply(this, args)
// subClass 子类
// superClass 父类
var jc = function (superClass, subClass) {
var prototype = Object.create(superClass.prototype)
subClass.prototype = prototype
prototype.constructor = subClass
}
// 继承2
var jc2 = function (superClass, subClass) {
var F = function() {}
F.prototype = superClass.prototype
subClass.prototype = new F()
subClass.prototype.constructor = subClass
}
//实现一个基本的event bus
/** 构造函数
const bus = new Bus()
* on(type, fn)
* emit(type, data)
* ps: on是监听事件,添加事件,emit才是触发事件
*/
class Bus {
constructor () {
this.hashMap = new Map()
}
// 发送事件触发事件
emit (type, data) {
let handle = this.hashMap.get(type)
handle.call(this, data)
}
// 监听事件
on (type, fn) {
if(!this.hashMap.get(type)) {
this.hashMap.set(type, fn)
}
}
}
/**
/** 实现一个双向绑定
*
* data ={ val: '' }
* <input onInput={} value=data.val/>
*/
*/
function model () {
val data = {}
var input = document.getElementById('input')
input.addEventListener('input', function(e){
data.val = e.target.value
})
Object.defineProperty(data, 'val', {
enumrable: true,
configurable: true,
set: function(val, preval) {
if( val === preval) return
input.value = val
},
get: function(){
return data.value
}
})
}
/**
* /** 简单路由
* hash路由
*/
*/
class Route {
constructor() {
this.routes = []
this.currentHash = ''
this.freshRoute = this.freshRoute.bind(this)
window.addEventListener('load', this.freshRoute, false)
window.addEventListener('hashchange', this.freshRoute, false)
}
//存储
pushStore(path, cb) {
this.routes[path] = cb
}
// 更新
freshRoute () {
this.currentHash = location.hash.slice(1) || '/'
this.routes[this.currentHash]()
}
}
/**
* 手写ajax
*/
function ajax () {
//1.创建ajax对象
let xhr = new XMlHttpRequest()
//2. 打开链接
xhr.open(method, url, async)
//3 发送
xhr.send(data)
//4 接受处理
xhr.onreadystatechange = function(res) {
if (xhr.readyStatus === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
}
/**
* /**懒加载
* data-src
* img.offsetTop - document.documentElement.scrollTop < document.documentElement.clientHeight
* 遍历 满足条件 赋值src scroll
*/
var n = 0 // 避免重复从第一张图开始
function lazyLoad () {
var imgs = document.getElementbyTagName('img')
// 可视去高度
var clientHeight = document.documentElement.clientHeight || document.body.clientHeight
// 滚动高度
var srcollTop = document.documentElement.scrollTop || document.body.scrollTop
for (var i =n;i<imgs.length;i++) {
if ( img[i].offsetTop - scrollTop < clientHeight ) {
if(img[i].getAttribute('src') == '') {
img[i].src = img[i].getAttribute('data-src')
}
n = i + 1
}
}
}
window.addEventListener('scroll', lazyLoad)
/**
* 防抖 闭包保留 timer 定时器标志
* 在规定时间内,触发事件后,会重新计算延时时间
*/
function debounce(fn, delay) {
let timer = null
return function() {
var content = this
var arg = arguments
clearTimeout(timer)
timer = setTimeout(function(){
fn.call(this, ...arg)
}, delay)
}
}
/**
节流, 在规定时间内,多次粗发,只执行一次
*/
function throote (fn, s){
var timer = null
return function () {
var content = this
var arg = arguments
if(timer) return
timer = setTimeout(function(){
fn.call(content, ...arg)
timer = null
}, s)
}
}
// 利用闭包 包时间
function throte2(fn, s) {
var prevnow = +new Date()
return function() {
var content = this
var arg = arguments
let now = +new Date()
if(now - prevnow >= s) {
fn.apply(content, arg)
prevnow = +new Date()
}
}
}
//偏函数 将接收多个参数的函数变为接收一个参数,并接受剩余参数的新函数
function partial(fn) {
var conetnt = this
var args = [...arguments].slice(1)
return function(){
var finalargs = args.concat([...arguments])
fn.apply(conetnt, finalargs)
}
}
// 函数柯里化,将多参数函数变成接收单参的新函数
// fn(1,2,3,4) =>>> fnn(1)(2)(3)(4)
// 结合参数长度来判读是执行递归还是执行函数
function curry(fn) {
const firstargs = [].slice.call(arguments, 1)
return function() {
var args = [].slice.call(arguments)
if(firstargs){
args = firstargs.concat(...args)
}
if( args.length < fn.length ){
//实参小于新参数,则递归
return curry.call(this, fn, ...args)
}else{
return fn.apply(this, args)
}
}
}
// 调用
function fn(a,b,c,d) {console.log(a+b+c+d)}
var curfn = curry(fn)
curfn(1)(2)(3)(4) // 10
/**
* 实现一个json.stringify
* Boolean|Number|string 类型会自动转换为原始值
* undefined,函数以及symbol, 会被忽略
* 不可枚举的属性会被忽略
* 如果属性指向自身,即循环引用,属性会被忽略
*/
function josnStringify(obj) {
let type = typeof obj
if(type !== 'object' || type === null) {
if(/string|undefined|function/.test(type)) {
obj = '"' + obj + '"'
}
return String(obj)
}else {
let json = []
arr = (obj && obj.constructor === Array)
for(let k in obj) {
let v = obj[k]
let type = typeof v
if(/string|undefined|function/.test(type)) {
v = '"' + v + '"'
}else if(typeof === 'object') {
v = josnStringify(v) // 递归
}
// **
json.push((arr ? "" : '"' + k + '":') + String(v))
}
// 返回
return (arr ? '[' : '{') + String(json) + (arr ? ']' : '}')
}
}
/** 实现一个 json.parse
* eval('('+arg+')') ,不建议使用,会有安全隐患
* 第二种方式: new Function()
*/
var jsonStr = '{"age": 20, "name": "jack"}'
var json = (new Function('return ' + jsonStr))()
手写javascript 方法(升级)
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...