function _new(){
var obj = {}
var [constructor, ...args] = arguments
obj.__proto__ = constructor.prototype
constructor.apply(obj, args)
return obj
}
function People(name){
this.name = name
this.printName = function(){
console.log(this.name)
}
}
var p = _new(People,"zrz")
Function.prototype._call = function(context){
if(typeof this !== "function"){
throw new Error("not function")
}
context = context || window // 方法没有指定新的this指向,默认this指向window
context.fn = this
// 参数
let res = context.fn(...([...arguments].slice(1))) // 注意arguments不能直接直接使用数组的方法,需要利用...将其转化为数组
delete context.fn
return res
}
Function.prototype._apply = function(context){ // 参数以数组的形式传递
if(typeof this !== "function"){
throw new Error("not function")
}
context = context || window // 方法没有指定新的this指向,默认this指向window
context.fn = this
let res;
if(arguments[1]){
res = context.fn(...arguments[1])
}else{
res = context.fn()
}
delete context.fn
return res
}
// bind 返回一个函数 函数没有执行,需要手动调用
// bind参数可以多次传递
// 若bind生成的函数被new,this指向改变为当前函数的实例
Function.prototype._bind = function(context){// 返回function
if(typeof this !== "function"){
throw new Error("not function")
}
context = context || window
var _this = this
var args = [...arguments].slice(1)
var func = function(){
return _this.apply(this instanceof func ? this : context, args.concat([...arguments]))
// this instanceof func -- 使用new来调用绑定函数,此时绑定函数中this指向是new创建的新对象
}
if(this.prototype){ // 原型关系
func.prototype = this.prototype
}
return func
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Debounce 防抖</title>
</head>
<body>
<script>
function debounce(fn, time){
var start = Date.now()
var context = this
return function(...args) {
if(Date.now() - start < time){
start = Date.now()
}else{
fn.apply(context, args) // 第一次触发执行
start = Date.now()
}
}
}
function debounce2(fn, time){
var start = Date.now()
var context = this
var timeout = null
return function(...args){
if(timeout){
clearTimeout(timeout)
timeout = null
}
timeout = setTimeout(() => {
fn.apply(context,args) // 最后一次触发执行
clearTimeout(timeout)
timeout = null
}, time);
}
}
window.onresize = debounce2(()=>{
console.log('resize')
}, 1000)
</script>
</body>
</html>
//throttle 节流 -- n秒内只执行一次
function throttle(fn, time){
var start = Date.now() // 利用闭包来保存时间
// console.log(this, arguments) // this为window
return (function(){
// console.log(this, arguments) // this为button
if(Date.now() - start >= time){
// fn.call(context, arguments)
fn()
start = Date.now()
}
})
}
function throttle2(func, time){
var context = this,
timer = null
return function(...args) {
if (timer) {
return;
}
timer = setTimeout(() => {
func.apply(context, args)
clearTimeout(timer)
timer = null
}, time)
}
}
window.onresize = throttle(function() {
console.log('1111');
}, 1000)
/**
* instanceof: 判断一个对象是否是一个对象的实例
* instanceof右侧对象原型对于左侧对象原型链上
*/
function _instanceof(left, right){
let leftValue = left.__proto__
let rightValue = right.prototype
while(true){
if(leftValue === null)return false
if(rightValue === leftValue)return true
leftValue = leftValue.__proto__
}
}
var obj = {}
console.log(_instanceof(obj, Object)) // true
console.log(obj instanceof Object) // true
let a = 12
console.log(_instanceof(a,Number)) // true -- a为基本数据类型,结果为false (_instanceof没有考虑到这种情况)
console.log(a instanceof Number) // false
/**
* 数组扁平化flat -- 数组降维
* 对原数组没有改变,返回一个新数组
* 没有参数:默认拉平一层
* 传入一个参数:拉平的层数
* 参数为infinity,数组拉平为一维数组
* 如果原数组中存在空位,跳过
*/
// 数组完全铺平
// 借助函数
function flat(array){
var _flat = function(array, output) {
for(var i = 0; i < array.length; i++) {
var item = array[i]
if (Array.isArray(item)) {
_flat(item, output)
} else {
output[output.length] = item;
}
}
}
var output = []
_flat(array, output)
return output;
}
// forEach遍历数组
function _flat(array){
var res = []
array.forEach(item => {
if(Array.isArray(item)){ // concat方法进行数组的拼接,concat方法返回一个新数组,不改变原数组
res = res.concat(arguments.callee(item)) // callee方法递归执行本身函数
}else{
res.push(item)
}
})
return res;
}
var array = [1,,2,3,[3,4,5,[6,[9,0],7]],8,9]
// console.log(_flat(array)) // [1,2,3,4,4,5,6,7,8,9]
// 用reduce实现flat
function _flat2(array){
// reduce利用concat展开一层
// return array.reduce((pre, cur)=>{
// return pre.concat(cur)
// },[])
// reduce 全部展开
return array.reduce((pre, cur)=>{
return pre.concat(Array.isArray(cur) ? _flat2(cur) : cur)
},[])
}
// console.log(_flat2(array))
// 利用栈实现flat函数 完全展开数组
function _flat3(){
var res = []
var stack = array
var item = null
while(stack.length > 0){
item = stack.shift()
if(Array.isArray(item)){
stack.unshift(...item)
}else{
res.push(item)
}
}
return res
}
// console.log(_flat3(array))
// 通过传入参数来控制拉平的层数 -- 拉平n层
function _flat4(array, n = 1) {
// reduce
return array.reduce((pre, cur)=>{
return pre.concat((Array.isArray(cur) && n > 1) ? (
_flat4(cur, n-1)
) : cur)
},[])
}
// console.log(_flat4(array, 2))
// 在原型上重写flat函数,传入参数表示要拉平的层数
Array.prototype._flat = function(num){
var arr = this
while(num > 0){
if(arr.some(item => Array.isArray(item))){ // 数组中有数组元素
// 拉平一层
arr = arr.reduce((pre, item)=>{
return pre.concat(item) // concat不会改变原数组,reduce的return返回值被累加
},[])
}
num--
}
return arr
}
console.log(array._flat(2))
// 考虑数组空位的情况
// 上面的reduce实现的数组扁平化就可以跳过空格 -- 大多数数组的处理方法都会跳过空格:ForEach、filter、reduce、every、some
// 柯里化 -- 将一个函数转化为一系列函数,例如:函数add(a,b,c)返回三个参数相加的结果,柯里化为add(a)(b)(c)表示三个数相加 -- 闭包思想实现
function multi2(){
var args = arguments // 数组
return function(){
if(arguments.length === 0){
return [...args].reduce((pre, item)=>{
return pre * item
},1)
}
return multi2.call(this, ...args, ...arguments)
}
}
console.log(multi(2)(3)(4)())
// 方法一
function copy2(obj){
return JSON.parse(JSON.stringify(obj)) // 遇到undefined和function无效
}
// 方法二
// 深拷贝
function isBaseType(n){
// 判断是否为基本数据类型
var typeArr = ['string', 'number', 'boolean', 'null', 'undefined',]
var type = typeof n
return typeArr.indexOf(type) !== -1
}
// 闭包对判断类别的方法进行封装
var typeCheck = {}
function createCheckTypeFn(type){
return (function(value){
return Object.prototype.toString.call(value) === `[object ${type}]`
})
}
const types = ['Array','Object','Function']
for(let i=0;i<types.length;i++){
typeCheck[`is${types[i]}`] = createCheckTypeFn(types[i])
}
function copy(obj){
if(isBaseType(obj) || typeCheck.isFunction(obj)){
return obj
}
var res;
if(typeCheck.isArray(obj)){
res = []
}else if(typeCheck.isObject(obj)){
res = {}
}
for(let key in obj){
res[key] = copy(obj[key])
}
return res
}
var obj = {
name: "zrz",
age: 10,
scores: {
math :100,
english: undefined
},
printName: function(){
console.log(this.name)
}
}
// 手写Ajax
function ajax({url, type, data, dataType}){
return new Promise((resolve, reject)=>{
// 1. 创建异步请求对象
var xml = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
// 2. 绑定监听事件
// ajax请求被发送到服务器,需要基于响应的状态,readyState有5中状态 0-4分别表示:请求未初始化、连接建立、请求接收、请求处理、请求完成响应就绪,readySate改变,触发onreadystatechange事件
xml.onreadystatechange = function(){
// readyState变为4 并且 返回状态码为200时 接收响应成功
if(xml.readyState === 4 && xml.status === 200){
// 转化返回的数据类型
var res;
if(dataType.toLowerCase() === 'json'){
res = JSON.parse(xml.responseText)
}else{
res = xml.responseText
}
resolve(res)
}
}
// 如果是get请求,请求参数添加到url后面
if(type.toLowerCase() === 'get' && data !== undefined){
url += '?'+data
}
// 3. 打开连接
xml.open(type, url, true)// true -- 异步
// 请求方式为post,修改请求头信息
if(type.toLowerCase() === 'post'){
// 设置请求头信息
xml.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
}
// 4. 发送请求
if(type.toLowerCase() === 'post' && data !== undefined){
xml.send(data) // post方式的send
}else{
xml.send(null)
}
})
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>红绿黄灯</title>
<style>
.box{
width: 100px;
height: 100px;
background-color: red;
border-radius: 50px;
}
.timer{
width: 100px;
text-align: center;
}
</style>
</head>
<body>
<div class="box"></div>
<p class="timer"></p>
<script>
var config = {
"red": 3,
"green": 4,
"yellow": 2
}
var arr = ['green', 'yellow', 'red']
var box = document.getElementsByClassName('box')[0]
var timerDom = document.getElementsByClassName('timer')[0]
function updateTimerStyle(time){
timerDom.innerHTML = time
}
function stayLight(color, time){
box.style.backgroundColor = color
timerDom.style.color = color
updateTimerStyle(time)
return createTimer(time)
}
function createTimer(time){
return new Promise(resolve => {
var timer = setInterval(()=>{
time--
if(time === 0){
clearInterval(timer)
timer = null
resolve()
return;
}
updateTimerStyle(time)
}, 1000)
})
}
async function light(){
while(true){
await stayLight(arr[0], config[arr[0]])
await stayLight(arr[1], config[arr[1]])
await stayLight(arr[2], config[arr[2]])
}
}
light()
</script>
</body>
</html>
var obj = {
name: 'ggg',
age: '12',
score: 122
}
Object.prototype[Symbol.iterator] = function(){
var self = this
var i = 0
var arr = Object.keys(self)
var len = arr.length
return {
next: function() {
if(i < len){
return {
value: self[arr[i++]],
done: false
}
}else{
return {
value: undefined,
done: true
}
}
}
}
}
for(let item of obj){
console.log(item)
}
常见手写函数
最新推荐文章于 2023-11-30 18:01:54 发布