//手写call函数
//判断调用对象是否为函数
//判断传入上下文是否存在,不存在则为window
//截取第一个参数后的所有参数
//将函数作为上下文对象的属性
//使用上下文对象调用方法并返回结果
//删除刚才新增的属性
//返回结果
Function.prototype.mycall = function(context){
//判断调用对象(必须是函数调用)
if(typeof this !== "function"){
console.error("type error");
}
//获取参数
let args = [...arguments].slice(1);
result = null;
//判断context是否传入,没有的话设置为window
context = context || window;
//将调用函数设置为对象的方法
context.fn = this;
//执行函数
result = context.fn(...args);
//删除属性
delete context.fn;
return result;
}
//手写bind
//判断调用对象是否为函数
//保存当前函数的引用,获取其余传入参数值
//创建一个函数返回
//函数内部使用apply绑定函数调用,判断函数作为构造函数的情况,
//这时候需要传入当前函数的this给apply调用,其余都是指定上下文
//
Function.prototype.myBind = function(context){
//判断是否为函数
if(typeof this !== "function"){
throw new TypeError("error");
}
//获取参数
var args = [...arguments].slice(1);
fn = this;
return function Fn(){
//根据调用方式,传入不同绑定值
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
)
}
}
//手写apply
Function.prototype.myApply = function(context){
//判断调用对象是否为函数
if(typeof this !== "function"){
throw new TypeError("error!")
}
let result = null;
//判断context是否存在,未传入则设置为window
context = context || window;
//将函数设置为对象
context.fn = this;
if(arguments[1]){
result = context.fn(...arguments[1]);
}else{
result = context.fn()
}
//删除属性
delete context.fn;
return result;
}
//手写ajax
//asyncchronous javascript and xml
//创建步骤:创建xmlhttprequest
//在对象上用open方法创建一个http请求(参数:请求方法,请求地址,是否异步,用户认证信息)
//setRequestheader 添加信息和监听函数
//XMLhttprequest有5个状态,改变时触发onReadystateChange
//4:服务器接受完成, 2、3:返回正常
//response更新页面
//调用sent方法向服务器发起请求
const SERVER_URL = "/server";
let xhr = new XMLHttpRequest();
//创建http请求
xhr.open("GET", SERVER_URL, true);
//设置状态监听函数
xhr.onreadystatechange = function(){
if(this.readyState !== 4){
return;
}
//请求成功
if(this.readyState === 200){
handle(this.response)
}else{
//输出错误信息
console.error(this.statusText)
}
//设置请求失败时的监听函数
xhr.onerror = function(){
console.log(this.statusText);
}
//设置请求头信息
xhr.responseType = "json";
xhr.setRequestHeader("Accept","application/json");
//send方法发送http请求
xhr.send(null);
}
//实现深拷贝
//深浅拷贝区别:浅:把对象属性复制到另一对象,应用类型则把地址复制给对象
//深:遇到属性值为引用类型,新建一个引用类型并赋值,所以将获得一个新的应引用类型
//属性里边存在函数或者symbol时会转换失败
//JSON.parse.(JSON.stringify(obj)):先序列化再反序列化还原,但对存在函数和symbol的对象不行
let obj1 = {
a:0,
b:{
c:0
}
}
let obj2 = JSON.parse(JSON.stringify(obj1));
obj1.a = 1;
obj1.b.c = 1;
console.log(obj1);
console.log(obj2);//修改obj1的内容2不会改变
//实现数组的乱序输出
//取出数组的第一个元素,随机产生一个随机值与这个元素进行交换
//再次取出数组第二个元素,产生一个除了索引值为1以外的索引值,将第二个元素与该索引值对应的元素进行交换
//每一个元素重复操作
var arr = [1,2,3,4,5,6,7,8,9,10]
for(var i=0;i<arr.length;i++){
const randomIndex = Math.round(Math.random() * (arr.length - 1 - i)) + i;
//交换位置
[arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];
}
console.log(arr)
//实现数组扁平化
//递归实现,遍历每一个元素,如果遇到数组就继续往下遍历,知道全部输出为止
let arr = [1,[2,[3,4,5]]];
function flatton(arr){
let result = [];
for(let i=0;i<arr.length;i++){
if(Array.isArray(arr[i])){
//是数组则进入递归
result = result.concat(flatton(arr[i]));
}else{
result.push(arr[i])
}
}
return result
}
flatton(arr);
//reduce函数迭代
function flatton(arr){
return arr.reduce(function(prev, next){
return prev.concat(Array.isArray(next) ? flatton(next) : next)
},[])//立即执行函数
}
//扩展运算符实现
//实现数组去重
//ES6
const array = [1,2,3,4,5,6,7,8,8,8,7]
Array.from(new Set(array))
//ES5
function uniqueArray(array){
let map = {};
let res = [];
for(var i = 0;i<array.length;i++){
if(!map.hasOwnProperty([array[i]])){
map[array[i]] = 1;
res.push(array[i])
}
}
return res;
}
//实现 add(1)(2)(3)
//函数科里化
//粗暴版
function add(a){
return function(b){
return function(c){
return a+b+c
}
}
}
console.log(a+b+c)
//函数科里化
var add = function(m){
var temp = function(n){
return add(m+n)
}
temp.toString = function(){
return m;
}
return temp;
}
console.log(add(3)(4)(5))
//参数长度不固定
function add(...args){
return args.reduce((a,b) => a+b)
}
function curring(fn){
let args = [];
return function temp(...newArgs){
if(newArgs.length){
args = [
...args,
...newArgs
]
return temp
}else{
let val = fn.apply(this, args)
args = []//保证再次调用时为空
return val
}
}
}
//ES5求参数和
function sum(){
let sunm = 0;
Array.prototype.forEach.call(arguments, function(item){
sum += item * 1;
})
}
//ES6求参数和
function sum(...nums){
let sum = 0;
nums.forEach(function(item){
sum += item * 1;
})
return sum
}
console