- 构造函数有
prototype指向构造函数的原型 - 原型有
constructor指向将此对象作为原型的构造函数 - 对象有
_prototype_指向对象实例的原型 - 原型也是一个实例对象可以有链的下一节点,底部节点为Object构造与object原型
一些问题
- 方法定义在构造函数中,每个实例有单独的构造方法,在内存中是独立的。方法定义在原型上,调用的是原型的方法,同一块内存,==值为true。
__proto__是非标准属性,如果要访问一个对象的原型,建议使用 ES6 新增的Reflect.getPrototypeOf或者Object.getPrototypeOf()方法,而不是直接obj.__proto__,因为非标准属性意味着未来可能直接会修改或者移除该属性。同理,当改变一个对象的原型时,最好也使用ES6提供的Reflect.setPrototypeOf或Object.setPrototypeOf。
let target = {};
let newProto = {};
Reflect.getPrototypeOf(target) === newProto; // false
Reflect.setPrototypeOf(target, newProto);
Reflect.getPrototypeOf(target) === newProto; // true
复制代码
- 函数都会有
prototype,除了Function.prototype.bind()之外。 - 对象都会有
__proto__,除了Object.prototype之外(其实它也是有的,之不过是null)。 - 所有函数都由 Function 创建而来,也就是说他们的
__proto__都等于Function.prototype。 Function.prototype等于Function.__proto__。
构造函数
- 箭头函数不可用作构造函数,因为没有自己的this指针,值来源于上下文继承值。 构造函数普通调用会把对象原型和特征值方法等赋给最近的this或window
New 操作符
new操作符的工作流程
- 创建一个空对象
- 将
__prototype__指向构造函数的prototype - 改变this指向到新对象
- 如果构造函数没有返回对象,那么new自动返回第一步的这个新对象
function myNew(Creater,...args){
//判断
if (typeof Creater !== 'function') return new Error('type err');
//生成新对象并继承
let obj = {};
let res = Creater.call(obj,...args);
obj.__proto__ = Object.create(Creater.prototype);
// Object.setPrototypeOf(obj,Creater.prototype);官方MDN表示性能差不推荐
obj.constructor = Creater;
//判断函数本身的返回是否为引用类型
let isObject = typeof res === 'object' && res !== null;
let isFunction = typeof res === 'function';
return (isFunction || isObject)? res:obj;
}
es5继承
call apply bind
call/apply
- 判断是否一个参数都每,如果没有则把主体设为window
- 生成唯一值作为主题临时函数的函数名防止冲突
- 把this函数绑定在主体上
- 执行并保存结果
- 删除主体的函数并返回结果
- call与apply区别是一个是扩展参一个是数组
Function.prototype.myCall = function (obj,...arr){
let myObj = obj ? Object(obj) : window;
let key = Symbol('soga');
myObj[key] = this;
let res = myObj[key](...arr);
delete myObj[key];
return res;
}
bind
- 判断this不是函数抛出异常
- 定义this变量fn在后面的function里用
- 定义要返回的结果函数,参数为扩展数组
- 结果函数为用新的obj执行this,但是如果使用了new(调用时候的this是当前函数的原型构造来的)则就使用new出来的this。第二个参数为柯里化两部分参数的链接。
- 使结果函数的原型指向当前函数的原型,防止后续操作污染当前函数原型添加一层空的函数层来链传递指向。
- 返回结果
Function.prototype.myBind = function (obj,...arr){
if (typeof this !== 'function'){
throw new Error("not a function!");
}
let fn = this;
let res = function (...arr2){
fn.apply(this instanceof fn? this : obj,[...arr,...arr2]);
}
res.prototype = Object.create(fn.prototype);
return res;
}