手写JavaScript代码

实现一个new

首先说说new操作符的作用

  1. new操作符会返回一个对象,所以我们需要在内部创建一个对象。
  2. 这个对象,也就是构造函数中的this,可以访问到挂载在this上的任意属性。
  3. 这个对象可以访问到构造函数原型上的属性,所以需要将对象与构造函数链接起来。
  4. 返回原始值需要忽略,返回对象需要正常处理。
//第一种写法
function _new(){
	let obj = {}
	let Con = [].shift.call(arguments)//获取构造函数
	if(typeof Con !== 'function'){
		return new Error('参数必须是一个函数');
	}
	obj.__proto__ = Con.prototype //实例与构造函数相关联
	let result = Con.apply(obj,arguments)//绑定this
	return result instanceof Object ? result : obj //返回
}
//第二种写法,主要用了ES6的数组展开
function _new(fn,...args){
	if(typeof fn !== 'function'){
		return new Error('参数必须是一个函数');
	}
	let obj = Object.create(fn.prototype)
	let result = fn.apply(obj,args)
	return result instanceof Object ? result : obj //返回
}
//构造函数
function Car(name){
	this.name = name
}
Car.prototype.sayName = function(){
	console.log('Name is '+ this.name)
}
let car1 = _new(Car,'BMW')
console.log(car1)//Car {name: "BMW"}
console.log(car1.sayName())//Name is BMW

实现一个instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。如果出现返回true,否则返回false;

function _instanceof(a,b){
	while (a) {
	//逐层查找
		if (a.__proto__ === b.prototype) return true;
		a = a.__proto__; 
	}
	return false; //找不到返回false
}

实现一个继承

这里主要是call+原型链组合继承

// 基类
function Base() {
}
// 派生类
function Derived() {
    Base.call(this); //主要用来继承属性
}
// 将派生类的原型的原型链挂在基类的原型上
//主要用来继承方法
Object.setPrototypeOf(Derived.prototype, Base.prototype);

手写 bind、call 和 apply

它们3个都是用来改变this的指向,apply第二个参数只能传数组,bind可以修改this指向后不立即执行函数;

  1. bind
Function.prototype._bind = function(context = window, ...bindArgs){
	//context 默认为window
	const func = this //调用_bind的原函数
	if (typeof func !== 'function') {
	  throw new TypeError('调用_bind()必须是一个函数');
	}
	//返回一个绑定 this 的函数
	return function(...callArgs){
		let args = bindArgs.concat(callArgs);
		if (this instanceof func) {
		  // 意味着是通过 new 调用的 而 new 的优先级高于 bind
		  return new func(...args);
		}
		return func.call(context, ...args);//改变this指向
	}
}
  1. call
Function.prototype._call = function(context = window, ...args){
	context.func = this; //绑定该函数为某对象的方法
	if (typeof context.func !== 'function') {
	  throw new TypeError('调用_call()必须是一个函数');
	}
	//调用方法,并返回结果
	let res = context.func(...args);
	delete context.func;
	return res;
}
  1. apply
Function.prototype._apply = function(context = window, args = []) {
  context.func = this;
  if (typeof context.func !== 'function') {
    throw new TypeError('调用_apply()必须是一个函数');
  }
  let res = context.func(...args);
  delete context.func;
  return res;
}

实现jsonp

<script>标签的src属性并不被同源策略所约束,所以可以获取任何服务器上脚本并执行。
JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。将JSON数据填充进回调函数。
前端代码:

var script = document.createElement('script');
script.type = 'text/javascript';
 // 传参并指定回调执行函数为onBack
 script.src = 'http://127.0.0.1:1111?callback=onBack';
 document.head.appendChild(script);
 // 回调执行函数
 function onBack(res) {
	console.log(res)//{id: "dsji3241", name: "wangwu", age: 18}
 }

后台代码:
使用了express框架创建服务

const express = require('express')
const app = express();
app.get('/',(req,res)=>{
	let query = req.query
	let callback = query.callback
	let data = {id:'dsji3241',name:'wangwu',age:18}
	res.end(callback + '(' + JSON.stringify(data) + ')')
})
app.listen(1111,()=>{
	console.log('server running at 1111')
})

实现ajax

function myAjax(options){
var method = options.method || 'GET'
	params = options.params,
	data = options.data,
	url = options.url + (params ? '?' + Object.keys(params).map(key => key + '=' + params[key]).join('&') : ''),
	asy = options.asy === false ? false : true,
	success = options.success,
	headers = options.headers;
	var request;
	if (window.XMLHttpRequest) {
	  request = new XMLHttpRequest();
	} else {
	  request = new ActiveXObject('Microsoft.XMLHTTP');
	}
	request.onreadystatechange = function() {
	    if (request.readyState === 4 && request.status === 200) {
	      success && success(request.responseText);
	    }
	}
	request.open(method, url, asy);
	if (headers) {
		Object.keys(headers).forEach(key => request.setRequestHeader(key, headers[key]));
	}
	method === 'GET' ? request.send() : request.send(data);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值