vue 源码使用到的原型 #
使用 new 创建实例 。执行 init 方法,_init 方法构造函数没有此方法,往原型对象上找 此处使用 new 创建出来的 this,必定指向 VUE。
- new 干了什么?
- instanceof 判断逻辑?
var app = new Vue({
data:{},
watch:{}
})
function Vue(options) {
if (process.env.NODE_ENV !== "production" && !(this instanceof Vue)) {
warn("Vue is a constructor and should be called with the `new` keyword");
}
this._init(options);
}
initMixin(Vue);
Vue源码使用到的原型
if (Array.isArray(value)) {
// 通过能力检测的结果选择不同方式进行数组劫持
if (hasProto) {
protoAugment(value, arrayMethods); //如果浏览器支持隐式原型
} else {
copyAugment(value, arrayMethods, arrayKeys);
}
this.observeArray(value);
} else {
this.walk(value);
}
// can we use __proto__?
export const hasProto = '__proto__' in {}
function protoAugment(target, src: Object) {
/* eslint-disable no-proto */
target.__proto__ = src;
/* eslint-enable no-proto */
}
MDN:通常,应该使用 Object.setPrototypeOf() 方法来设置对象的原型
源码中为什么使用_proto_
而没有使用 setPrototypeOf
为什么要使用原型 #
function Foo(name) {
this.name = name;
this.showName = function () {
console.log("I'm " + this.name);
};
}
图上通过 Foo 创建出来的每一个对象,里面都有 showName 这样就会占用很多的资源。
function Foo(name) {
this.name = name;
}
Foo.prototype.showName = function () {
console.log("I'm " + this.name);
};
- 而通过原型来实现的话,只需要在构造函数里面给属性赋值,而把方法写在
Foo.prototype
属性 这样每个对象都可以使用 prototype 属性里面的方法,节省了不少的资源。 - 使用原型链解决继承问题
原型链笔记 #
- 每个对象都有一个
_proto_
属性,并且指向它的 prototype 原型对象 - 每个构造函数都有一个 prototype 原型对象-
- prototype 原型对象里的 constructor 指向构造函数本身 Person.prototype.constructor === Person
- 当试图得到一个对象的属性时,如果这个对象本身不存在这个属性就会根据proto去 prototype 找。因为还是一个对象继续找 Object
Object.create(null) #
Object.create(null) 新建的对象是没有__proto__属性的
hasOwnProperty #
在原型链上查询属性比较耗时,对性能有影响,试图访问不存在的属性时会遍历整个原型链。遍历对象属性时,每个可枚举的属性都会被枚举出来。 要检查是否具有自己定义的属性,而不是原型链上的属性
,必须使用 hasOwnProperty 方法。hasOwnProperty 是 JavaScript 中唯一处理属性并且不会遍历原型链的方法
new 干了什么? #
function myNew(Con, ...args) {
//1创建一个空对象
let obj = {};
//2将这个空对象的__proto__指向构造函数的原型
Object.setPrototypeOf(obj, Con.prototype);
//3改变this指向,讲空对象作为构造函数的上下文
var result = Con.apply(obj, args);
//4对构造函数有返回值的处理判断
// 当 构造函数有返回值时 则需要做判断再返回对应的值,是 对象类型则返回该对象,是 原始类型则返回第一步创建的空对象。
return result instanceof Object ? result : obj;
}
function Foo2() {
this.name = "aaa";
return 111;
}
console.log(new Foo2()); //这个返回值是基本类型,被忽略不影响结果
4 默认 如果返回的是基本类型return 111 则忽略返回结果 如果返回的是引用类型,则返回引用类型
instanceof 判断逻辑? #
instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype
function new_instance_of(leftVaule, rightVaule) {
let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
if(typeof leftVaule !== 'object' || leftVaule === null) {
return false
}
while (true) {
//最顶层的object的__proto__是null
if (leftVaule === null) {
return false;
}
if (leftVaule === rightProto) {
return true;
}
// 当原型对象不相同时, 沿着原型链继续向上查找
leftVaule = leftVaule.__proto__;
}
function Fun() {
// this.run = a;//2
}
// Fun.prototype.run = b;//4
var f1 = new Fun();
// f1.run = c; //1
// f1.__proto__.run = d;//3
// Object.prototype.run = e;//5
Function.prototype.run = f; //不会找
console.log(f1.run);