js之方法原理


数组

Array.prototype.map():映射原理
1
2
3
4
5
6
7
8
9
10
11
12
13
//自定义函数实现map功能
Array.prototype.myMap = function (fn) {
let arr = this
let newArr = []
for(let i = 0; i< arr.length; i++) {
let result = fn(arr[i], i)
newArr.push(result)
}
return newArr
}
[1,2,3].myMap((item, i) => {
return item + i
}) //[1,3,5]
Array.prototype.find()
1
2
3
4
5
6
7
8
9
Array.prototype.myFind = function(fn){
let arr = this
for(let i = 0; i<arr.length; i++) {
if (fn(arr[i],i)) {
return arr[i]
}
}
}
[{id: 1},{id:2},{id:3}].myFind((item, i) => { return item.id === 2}) // {id:2}
Array.prototype.filter():过滤原理
1
2
3
4
5
6
7
8
9
10
11
12
13
Array.prototype.myFilter = function(fn){
let arr = this
let newArr = []
for(let i = 0;i<arr.length;i++){
let result = fn(arr[i], i)
if (result){
newArr.push(arr[i])
}
}
return newArr
}

[1,2,3,4].myFilter((item, i) => {return item % 2 === 0})
Array.prototype.reduce():减少原理
1
2
3
4
5
6
7
8
9
Array.prototype.myReduce = function(fn, val){
let arr = this
let result = fn(val, arr[0])
for(let i=1; i<arr.length;i++){
result = fn(result, arr[i])
}
return result
}
[1,2,3,4].myReduce((x,y) => {return x+ y}, 0)
Array.prototype.every():对数组中每个元素进行判断
1
2
3
4
5
6
7
8
9
10
11
Array.prototype.myEvery = function(fn){
let arr = this
for(let i=0; i<arr.length; i++){
if (fn(arr[i], i)) {
} else {
return false
}
}
return true
}
[1,2,3].every((item, i) => {return typeof item === 'number'})

Function

Function.prototype.bind()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var obj = {}
obj.fn = function(){
let fn1 = function(a,b){
console.log(this, a,b)
}
let fn2 = fn1.myBind(this,1,2)
fn2()
}
Function.prototype.myBind = function(context){
context = context || window
context.fn = this
let arg = [...arguments].slice(1)
return function(){
context.fn(...arg)
}
}
obj.fn()
new 的原理
1
2
3
4
5
6
7
8
9
10
11
function create () {
let arg = [...arguments]
let constructor = arg[0]
let obj = new Object()
obj = Object.create(constructor.prototype)
constructor.apply(obj, arg.slice(1))
return obj
}
let Fn = function (a) { this.a = a }
Fn.prototype.say = function () { console.log('a', this.a) }
let obj = create(Fn, 1)
instanceof的原理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function _instanceOf(obj,fn){
var proto=obj.__proto__;
do{
if(proto===fn.prototype){
return true;
}else{
proto=proto.__proto__
}
}while(proto)
return false;
}
var arr=[1,2,3];
_instanceOf(arr,Array);//true
_instanceOf(arr,Object)//true
Function.prototype.call()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a = {
b(){
var fn = function(a,b,c){
console.log(this,a,b,c)
}
fn.myCall(this, 1, 2, 3)
}
}
Function.prototype.myCall = function(context){
!context && (context = window)
context.fn = this
context.fn(...[...arguments].slice(1))
}
a.b()
手写Promise
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function Promise1 (fn) {
this.value = undefined
this.reason = undefined
var that = this
Object.defineProperty(that, 'status1', {
get (){
return 'pending'
},
set (val){
that.status = val
that.thenFn()
}
})
this.status = 'pending'
var resolve = function(val){
that.value = val
that.status1 = 'fulfilled'
}
var reject = function(val){
that.reason = val
that.status1 = 'reject'
}
try {
fn(resolve, reject)
} catch(e) {
reject(e)
}
}
Promise1.prototype.then = function(resolve, reject){
this.thenFn = function(){
switch(this.status) {
case 'fulfilled':
resolve(this.value)
break
case 'reject':
reject(this.value)
break
}
}
}
实现双向数据绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<input />
<span></span>

let input = document.querySelector('input')
let span = document.querySelector('span')

let obj = {}
Object.defineProperty(obj, 'text', {
configure: false,
enumerable: false,
get (val) {
return val
},
set (val) {
console.log('数据更新了', val)
span.innerHTML = val
}
})

input.addEventListener('keyup', function(e){
obj.text = e.target.value
})
实现拖拽
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
window.onload = function () {
// drag处于绝对定位状态
let drag = document.getElementById('box')
drag.onmousedown = function(e) {
var e = e || window.event
// 鼠标与拖拽元素边界的距离 = 鼠标与可视区边界的距离 - 拖拽元素与边界的距离
let diffX = e.clientX - drag.offsetLeft
let diffY = e.clientY - drag.offsetTop
drag.onmousemove = function (e) {
// 拖拽元素移动的距离 = 鼠标与可视区边界的距离 - 鼠标与拖拽元素边界的距离
let left = e.clientX - diffX
let top = e.clientY - diffY
// 避免拖拽出可视区
if (left < 0) {
left = 0
} else if (left > window.innerWidth - drag.offsetWidth) {
left = window.innerWidth - drag.offsetWidth
}
if (top < 0) {
top = 0
} else if (top > window.innerHeight - drag.offsetHeight) {
top = window.innerHeight - drag.offsetHeight
}
drag.style.left = left + 'px'
drag.style.top = top + 'px'
}
drag.onmouseup = function (e) {
this.onmousemove = null
this.onmouseup = null
}
}
}