function jsonp(url,data,callback){
var funcName = 'jsonp_'+Date.now()+Math.random().toString().substr(2, 5)
//如果有其他参数需要拼接
if(typeof data==='object'){
var tmpArr = []
for (let key in data){
let value =data[key]
tmpArr.push(key+'='+value)
}
data = tmpArr.join('&')
}
let script = document.createElement('script')
script.src = url + '?' + data + '&callback= ' + funcName
document.body.appendChild(script)
window[funcName]= function (data){
callback(data)
//清除标签
delete Window[funcName]
document.body.removeChild(script)
}
}
★★★★ 手写深拷贝
javascript复制代码
//乞丐版
function deepCopy(obj){
return obj.JSON.Parse(JSON.Stringify(obj))
}
//面试够用版
function deepCopy(obj){
if(typeof obj)
if(typeof obj =='object'){//判断是否为复杂数据源类型
var result = obj.constructor == Array?[]:{} //数组还是对象
for(let i in obj){
result[i]= typeof obj[i] =='object'? deepCopy(obj[i]):obj[i]
}
}else{
//简单数据类型
var result = obj;
}
return result
}
★★★ 手写浅拷贝
javascript复制代码
function clone(target) {
if(target === null ) {
return target
}
// 克隆 数组 和 对象
let cloneTarget = Array.isArray(target) ? [] : {}
for (const key in target) {
if (target.hasOwnProperty(key)) {//判断是否是本身的属性
cloneTarget[key] = target[key]
}
}
return cloneTarget
}
★★★★ 手写 bind
javascript复制代码
Function.prototype.myBind = function(context) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
//返回一个绑定this的函数,这里我们需要保存this
const _this = this
const args = [...arguments].slice(1)
//返回一个函数
return function F() {
//因为返回一个函数,我们可以new F()需要判断能当做构造函数吗
if (this instanceof F) { //实例是F这个构造函数造出来的
return new _this(...args, ...arguments)
}
return _this.apply(context, args.concat(...arguments))
}
}
★★★★ 手写 call
javascript复制代码
Function.prototype.myCall = function(context) {
context=context||window //传入参数的话,就指定context为this指向,否则指定window
context.fn = this
const args = [...arguments].slice(1) //入参删除context
const result = context.fn(...args)
delete context.fn
return result
}
★★★★ 手写 apply
javascript复制代码
Function.prototype.myApply = function(context) {
context = context || window
context.fn = this //给传入的上下文对象添加一个fn方法,这个fn方法即为myApply调用者
let result
if(arguments[1]){
result = context.fn(...arguments[1])
}else{
result = context.fn()
}
delete context.fn
return result
}
★★★ 手写模拟 object.create
复制代码
function _create (obj){
function F(){} //创建一个构造函数
F.prototype = obj //将构造函数的原型对象赋值
return new F()
}
function _is(x, y) {
if (x === y) {
//运行到1/x === 1/y的时候x和y都为0,但是1/+0 = +Infinity, 1/-0 = -Infinity, 是不一样的
return x !== 0 || y !== 0 || 1 / x === 1 / y
} else {
//NaN===NaN是false,这是不对的,我们在这里做一个拦截,x !== x,那么一定是 NaN, y 同理
//两个都是NaN的时候返回true
return x !== x && y !== y
}
}
console.log(is(+0, -0))
console.log(is(NaN, NaN))
★★★ 手写 new
javascript复制代码
//new的实现过程(实际上就是调用这个构造函数,同时将构造函数的prototype上的属性方法挂上去。)
//1. 新建一个对象
//2. 对象 继承 构造函数的 原型链
//3. 将构造函数的this指向这个对象
//4. 根据构造函数的返回值的返回结构
function myNew(fn){
let obj = {} //定义空对象obj
obj = Object.create(fn.prototype) //将传入的构造函数的prototype属性方法复制到obj里面
let args = Array.prototype.slice.call(arguments,1)// 获取除去fn之外的参数
//或者 [...arguments].slice(1)
let result = fn.call(obj,...args) // 调用传入的构造函数,矫正this为obj,并传入args
return typeof result === 'object'||result instanceof Function? result : obj;
//如果构造函数返回引用类型,直接返回,否则返回obj
}
class Foo{
constructor(){
this.name = 'ciel'
this.arg = arguments[0]
}
callname(){
console.log(this.name)
}
}
// 测试
let test = myNew(Foo, 'hhh', '123', 'saf')
test.callName()
console.log(test.arg)
★★★ 手写对象扁平化
javascript复制代码
export function jsonFlatten(data) {
var result = {}
function recurse(cur, prop) {
if (Object(cur) !== cur) {
result[prop] = cur
} else if (Array.isArray(cur)) {
for (var i = 0, l = cur.length; i < l; i++) { recurse(cur[i], prop + '[' + i + ']') }
if (l === 0) { result[prop] = [] }
} else {
var isEmpty = true
for (var p in cur) {
isEmpty = false
recurse(cur[p], prop ? prop + '.' + p : p)
}
if (isEmpty && prop) { result[prop] = {} }
}
}
recurse(data, '')
return result
}
★★★ 手写数组扁平化
javascript复制代码
//第一种 正则表达式
function flatten(arr){
let str = JSON.stringify(arr);
return str.replace(/(\[\]))/g,'').split(',')
}
//第二种 递归
function flatten(arr, result = []) {
if (!Array.isArray(arr)) {
result.push(arr)
return result
}
for (let value of arr) {
flatten(value, result)
}
return result
}
//第三种 数组字符串方法
function flatten(arr) {
return arr.toString().split(',').map(ele => parseInt(ele))
}
//第四种
function flatten(arr){
while(arr.some(item => Array.isArray(item))){
arr = [].concat(...arr);
}
return arr;
}
★★★ 手写数组去重
javascript复制代码
//1.ES6的Set
function unique(arr){
ruturn Array.from(new Set(arr))
}
//2. 双层for循环
function unique(arr) {
let result = []
for (let i = 0, len = arr.length; i < len; i++) { //第一层遍历
let flag = false //进行标记
for (let k = i + 1, len = arr.length; k < len; k++) {
if (arr[i] === arr[k]) { //如果后面有重复的就跳过
flag = true
k = arr.length
}
}
if (!flag) result.push(arr[i]) //没有重复的,添加到数组中
}
return result
}
//3. 利用数组的indexOf方法
function unique(arr) {
let result = []
for (let i = 0, len = arr.length; i < len; i++) {
if (result.indexOf(arr[i]) === -1) result.push(arr[i])
}
return result
}
//4. 利用类似桶排序的方法
function unique(arr) {
let result = []
let bucket = []; //创建一个桶
for (let i = 0, len = arr.length; i < len; i++) {
bucket[arr[i]] = 1 //将有些桶标记
}
for (key in bucket) { //取出有标记的桶的下标
console.log(key);
result.push(Number(key))
}
return result
}
//5. 利用filter方法
function unique(arr) {
return arr.filter((ele, index) => (arr.indexOf(ele) === index)) //过滤
}
//6. 利用map方法
function unique(arr) {
return arr.map((ele, index) => {
if (arr.indexOf(ele) === index) return ele
})
}
//7.排序后进行数组
function unique(arr) {
arr.sort()
let result = []
arr.forEach((ele, index) => {
if (ele !== arr[index + 1]) result.push(ele)
})
return result
}
★★★ 手写模拟实现 async/await
javascript复制代码
★★★★ 手写实现发布/订阅模式
javascript复制代码
class Subject { //定义被观察者
constructor() {
this.observers = []
}
addObserver(observer) { //订阅
this.observers.push(observer)
}
removerObserver(observer) {//取消订阅
let index = this.observers.indexOf(observer)
if (index !== -1) {
this.observers.splice(index, 1)
}
}
notify() { //通知
this.observers.forEach(observer => {
observer.update()
})
}
}
class Observer { // 定义观察者
update() {
console.log('subject更新了');
}
subscribeTo(subject) {
subject.addObserver(this)
}
}
let subject = new Subject() //被观察者
let observer1 = new Observer() //观察者
observer1.subscribeTo(subject) //观察者进行订阅
let observer2 = new Observer() //观察者
observer2.subscribeTo(subject) //观察者进行订阅
subject.notify()
★★★★ 手写防抖
javascript复制代码
funtion debounce(fn,delay){
let timer = null
return ()=>{
clearTimeout(timer)
timer = setTimeout(()=>(fn())
,delay)
}
}
let a = debounce(()=>(console.log('防抖处理')),500)
function 点击事件(){
a()
}
★★★★ 手写节流
javascript复制代码
function throttle(fn, delay = 500) {
let lastTime, time
return function(){
let context = this;
let args = [].slice.call(arguments);
time = Date.now()
if (!lastTime || time - lastTime > delay) {
fn.apply(context)
lastTime = time
}
}
}
function fn(){
console.log('节流')
}
let a = throttle(fn, 1000)
function 点击事件(){
a()
}