1、call实现原理
Function.prototype.mycall = function (context) {
// 当context为null时,其值则为window
context = context || window;
// this为调用mycall的函数。将this赋值给context的fn属性
context.fn = this;
// 将arguments转为数组,并从下标1位置开始截取
let arg = [...arguments].slice(1);
// 将arg数组的元素作为fn方法的参数执行,结果赋值给result
let result = context.fn(...arg);
// 删除fn属性
delete context.fn;
// 返回结果
return result;
}
测试:
function add(c, d){
return this.a + this.b + c + d;
}
var obj = {a:1, b:2};
console.log(add.mycall(obj, 3, 4)); // 10
2、apply实现原理
Function.prototype.myapply = function (context) {
// 当context为null时,其值则为window
context = context || window
// this为调用myapply的函数。将this赋值给context的fn属性
context.fn = this;
// 如果未传值,则为一空数组
let arg = arguments[1] || [];
// 将arg数组的元素作为fn方法的参数执行,结果赋值给result
let result = context.fn(...arg);
// 删除fn属性
delete context.fn
// 返回结果
return result
}
测试:
function add(c, d){
return this.a + this.b + c + d;
}
var obj = {a:1, b:2};
console.log(add.myapply(obj, [5, 6])); // 14
3、bind实现原理
Function.prototype.mybind = function (context) {
// this为调用mybind的函数。将this赋值给变量_this
let _this = this;
// 将arguments转为数组,并从下标1位置开如截取
let arg = [...arguments].slice(1);
// 返回函数fn
return function fn(){
// 通过apply方法调用函数并返回结果。
return _this.apply(context, arg.concat(...arguments));
}
}
测试:
var obj = {
siteName: "zhangpeiyue.com"
}
function printSiteName() {
console.log(this.siteName);
}
var site = printSiteName.mybind(obj);
// 返回的是一个函数
console.log(site) // function () { … }
// 通过mybind使其this发生了变化
site();// zhangpeiyue.com
4、递归拷贝
function deepClone(obj) {
// 判断是否数组或对象,确定初始值
let copy = obj instanceof Array ? [] : {}
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
}
}
return copy
}
测试:
const obj = {
siteName:"张培跃",
info:{
age:18,
props:["阳光","帅气"]
}
}
const copy1 = deepClone(obj);
console.log(copy1 === obj);// false
console.log(copy1.info === obj.info);// false
console.log(copy1.info.props === obj.info.props);// false
console.log(copy1.siteName);// 张培跃
// 可避免setInterval因执行时间导致的间隔执行时间不一致
setTimeout (function () {
// do something
setTimeout (arguments.callee, 500)
}, 500)
6、手写new
function myNew (fun) {
return function () {
// 创建一个新对象且将其隐式原型指向构造函数原型
let obj = {
__proto__ : fun.prototype
}
// 执行构造函数
fun.call(obj, ...arguments);
// 返回该对象
return obj;
}
}
测试:
function Site(siteName, siteUrl) {
this.siteName = siteName;
this.siteUrl = siteUrl;
}
let obj = myNew(Site)("张培跃","http://www.zhangpeiyue.com");
// { siteName: '张培跃', siteUrl: 'http://www.zhangpeiyue.com' }
console.log(obj);
function query(sHref = window.location.href){
var obj = {};
var args = sHref.split('?');
if(args[0] == sHref) return obj;
var arr = args[1].split('&');
for(var i = 0;i< arr.length;i++){
var arg = arr[i].split('=');
obj[arg[0]] = arg[1];
}
return obj;
}
测试:
// 倘若你当前的地址是:http://zhangpeiyue.com/s?a=1&b=2
var result = query();
console.log(result);// { a: '1', b: '2' }
// 当然你也可以指定地址:
var result = query("http://zhangpeiyue.com/s?c=3&d=4");
console.log(result);// { c: '3', d: '4' }
8、手写instanceof
function instance_of(L,R){
L = L.__proto__;
R = R.prototype;
while (true){
if(L === null) return false;
if(L === R) return true;
L = L.__proto__;
}
}
测试:
function Box(){
}
var obj = new Box();
console.log(instance_of(obj,Box));// true
console.log(instance_of(obj,Function));// false
console.log(instance_of(obj,Object));// true
9、手写promise
(function (window) {
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class Promise{
constructor() {
// 状态,初始值为pending
this.state = PENDING;
// 状态值,初始值为undefined
this.result = undefined;
this.callbackArr = [];
// 将当前的状态更改为成功fulfilled,值更改为value
function _resolve(value){
// console.log("我是最后输出的")
// 如果状态已经更改了,那么直接返回
if(this.state !== PENDING) return;
this.state = FULFILLED;
this.result = value;
this.callbackArr.forEach(item=>{
item.onResolved();
})
}
//将当前的状态更改为成功rejected,值更改为value
function _reject(value){
// 如果状态已经更改了,那么直接返回
if(this.state !== PENDING) return;
this.state = REJECTED;
this.result = value;
this.callbackArr.forEach(item=>{
item.onRejected();
})
}
try{
executor(_resolve.bind(this),_reject.bind(this));
}catch (e) {
// 发生异常之后,需要将状态更改为失败,值更改为e
_reject.call(this,e);
}
}
then(onResolved,onRejected) {
if(!(onRejected instanceof Function)){
// console.log("不是函数",onRejected)
onRejected = reason => {
throw reason;
}
}
// 1、返回了一个Promise实例。
return new Promise((resolve,reject)=>{
function _common(cb) {
setTimeout(()=>{
try{
const value = cb(this.result);
// 如果value是Promise,那么返回的Promise的状态,值与value相同
if(value instanceof Promise){
// 将上面注释代码简化:
value.then(resolve,reject);
}else{
// 不是promise,将返回的Promise的状态更改为成功,值为value
resolve(value);
}
}catch (e) {
reject(e);
}
})
}
if(this.state === FULFILLED){
_common.call(this,onResolved);
}
else if(this.state === REJECTED){
_common.call(this,onRejected);
}else{
this.callbackArr.push({
// 当状态成功执行onResolved
onResolved:_common.bind(this,onResolved),
// 当状态失败执行onRejected
onRejected:_common.bind(this,onRejected)
})
}
// console.log("then",this.state);
})
}
catch(onRejected) {
this.then(undefined,onRejected);
}
static resolve = function (value) {
if(value instanceof Promise){
return value;
}else{
// 不是promise, 返回一个成功状态的promise
return new Promise(function (resolve) {
resolve(value);
})
}
}
static reject = function (value) {
return new Promise(function (resolve,reject) {
reject(value);
})
}
static all = function (arr) {
const result = new Array(arr.length);
let i = 0;
return new Promise(function (resolve,reject) {
arr.forEach((item,index)=>{
item.then(value=>{
result[index] = value;
i++;
if(i===arr.length){
resolve(result);
}
},reason=>{
reject(reason);
})
})
})
}
static race = function (arr) {
return new Promise(function (resolve,reject) {
arr.forEach(item=>{
item.then(value=>{
resolve(value);
},reason=>{
reject(reason);
})
})
})
}
}
window.Promise = Promise;
})(window)
10、最后出道易错面试题
// 输出结果是?
function fn1() {
console.log(1);
}
function fn2() {
console.log(2);
}
fn1.call(fn2);
fn1.call.call(fn2);