重写内置的new和Object.create
重写内置的new
new 一个函数所具备的功能
- new 一个函数执行的时候,是把他当做构造函数执行的
- 先创建一个类,再创建一个类的实例,在当前实例的执行上下文中会默认创建一个对象,让函数体当中的this指向这个对象
- 函数正常执行完毕,最后看函数当中有没有return
- 如果没有return,默认把实例返回
- 如果有return, 看返回的数据类型
- 如果返回的是值类型,则依旧返回默认的当前实例
- 如果返回的是引用类型值,则用返回的引用类型值替换默认的当前实例
EG:实现以下效果
function Dog(name) {
this.name = name;
}
Dog.prototype.bark = function () {
console.log('wangwang');
}
Dog.prototype.sayName = function () {
console.log('my name is ' + this.name);
};
let sanmao = _new(Dog, '三毛');
sanmao.bark(); //=> "wangwang"
sanmao.sayName(); //=>"My name is 三毛"
console.log(sanmao instanceod Dog); //=> true
/*
* _new:创建摸一个类的实例
* params:
* Func:创建实例的这个类
* ...args:剩余的参数都是给Func这个函数传递的实参
*/
function _new(Func, ...args) {
/* 思路:
* 1. 创建Func的一个实例对象(对象.__proto__=== Func.prototype)
* 1)obj = {}; obj.__proto__ = Func.prototype;
* 2) obj = Object.create(Func.prototype);
* 2. 把类当做普通函数执行(THIS指向的是实例对象):result = Func.call(obj, ...args);
* 3. 看一下函数执行是否存在返回值,不存在或者返回的是值类型,则默认返回实例,如果返回的是引用数据类型则返回的不是实例而且自己写的引用类型值:if (result !== null && /^(object|function)$/.test(typeof result)) {return result;}; return obj;
*/
let obj,
result,
proto = Func.prototype,
ct = typeof Func;
//校验规则
if(Func === Symbol || Func === BigInt || typeof proto !== "function" || !proto ){
throw new TypeError(` ${Func} is not a constructor ! `);
};
obj = Object.create(Func.prototype);
result = Func.call(obj, ...args);
if (result !== null && /^(object|function)$/.test(typeof result)) {return result;};
return obj;
};
Object.create()
- 语法:let obj1 = Object.create([obj]);
- 意义:创建一个空对象(obj1) , 并且让
obj1.__proto__
指向 [obj], 把 [obj] 作为实例对象的原型 - [obj]:可以是一个对象或者是null,但是不能是其他值
- eg:obj = Object.create(Func.prototype); (上例中创建一个空的类)
重写Object.create
/*
* 重写Object.create:创建某个类的空实例
*/
Object.create = function create(prototype) {
if(prototype !== null && typeof prototype !== "object" ) throw new TypeError("Object prototype may only be an Object or null");
function Proxy() {};
Proxy.prototype = prototype;
return new Proxy;
};
Object.create(null) VS Object.create({})
var obj = Object.create(null);// 把obj.__proto__去掉了,浏览器断开了内置的原型链查找(破坏了原始的机制)
obj.__proto__ = Array.prototype;// 这仅仅是给obj设置了一个私有的属性__proto__
console.log(obj.slice);// 私有属性中没有slice =>undefined
var obj = Object.create({}); //=>这样不会破坏内置的原型链查找机制
obj.__proto__ = Array.prototype;
console.log(obj.slice);