专业的建设机械网站制作,织梦网站图片移动,app在线生成网站,seo点击工具了解原型、原型链前需要先了解构造函数#xff0c;new操作符 构造函数
构造函数是一种特殊的函数#xff0c;主要用来初始化对象#xff0c;即为对象成员变量赋初始值#xff0c;它总与 new 一起使用。我们可以把对象中一些公共的属性和方法抽取出来#xff0c;然后封装到… 了解原型、原型链前需要先了解构造函数new操作符 构造函数
构造函数是一种特殊的函数主要用来初始化对象即为对象成员变量赋初始值它总与 new 一起使用。我们可以把对象中一些公共的属性和方法抽取出来然后封装到这个函数里面。
function Foo () {this.name glthis.fun function () { console.log(eat)}
}const Foo function (){this.xxx xxx;
}const fooInstancing new Foo();
const fooInstancing1 new Foo();构造函数的三大特点
构造函数的函数名的第一个字母通常大写。函数体内使用this关键字代表所要生成的对象实例。生成对象的时候必须使用new命令来调用构造函数。
new操作符
new命令的作用就是执行一个构造函数并且返回一个对象实例。使用new命令时它后面的函数调用就不是正常的调用而是依次执行下面的步骤。
创建一个空对象作为将要返回的对象实例。将空对象的原型指向了构造函数的prototype属性。将空对象赋值给构造函数内部的this关键字。开始执行构造函数内部的代码。
也就是说构造函数内部this指向的是一个新生成的空对象所有针对this的操作都会发生在这个空对象上。 后续了解了原型之后我们再简单实现一个new
原型
在JavaScript没有class的时候是使用构造函数来新建一个对象的每一个构造函数的内部都有一个prototype属性它的属性值是一个对象(prototype)这个对象包含了可以由该构造函数的所有实例共享的属性和方法。当使用构造函数新建一个对象后在这个对象的内部将包含一个指针这个指针指向构造函数的 prototype 属性对应的值在 ES5 中这个指针(proto)被称为对象的原型。
一般来说不应该能够获取到这个值的但是现在浏览器中都实现了 proto 属性来访问这个属性但是最好不要使用这个属性因为它快芭比Q了。ES5 中新增了一个Object.getPrototypeOf() 方法可以通过这个方法来获取对象的原型。
结论
以上明白了 两点
prototype原型类型是对象一般叫原型对象是构造函数的proto、Object.getPrototypeOf(obj)是获取对象的原型prototype能干啥共享可以把那些不变的方法直接定义在 prototype 对象上这样所有对象的实例就可以共享这些方法。
// 构造函数本质是函数
function DoSomething(){}
console.log( DoSomething.prototype );
// 两种写法
var DoSomething function(){};
console.log( DoSomething.prototype );//
{constructor: ƒ}constructor: ƒ DoSomething()arguments: nullcaller: nulllength: 0name: DoSomethingprototype: {constructor: ƒ}[[FunctionLocation]]: VM1158:1[[Prototype]]: ƒ ()[[Prototype]]: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()__proto__: (...)get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()现在我们可以添加一些属性到 doSomething 的原型上面如下所示。
function DoSomething(){}
DoSomething.prototype.foo bar;
console.log( DoSomething.prototype ); // 然后我们可以使用 new 运算符来在现在的这个原型基础之上创建一个 doSomething 的实例。然后就可以在这个对象上面添加一些属性。
function DoSomething(){}
DoSomething.prototype.foo bar;
var doSomeInstancing new DoSomething();
doSomeInstancing.prop some value;
console.log( doSomeInstancing ); // __proto__哪去了
这时候会发现我们的__proto__哪去了对象实例里面咋没有凡事先看权威文档 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/proto proto 的读取器 (getter) 暴露了一个对象的内部 [[Prototype]] https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#%E7%BB%A7%E6%89%BF%E5%B1%9E%E6%80%A7 备注 遵循 ECMAScript 标准someObject.[[Prototype]] 符号是用于指向 someObject 的原型。从 ECMAScript 6 开始[[Prototype]] 可以通过 Object.getPrototypeOf() 和 Object.setPrototypeOf() 访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 proto。但它不应该与构造函数 func 的 prototype 属性相混淆。被构造函数创建的实例对象的 [[Prototype]] 指向 func 的 prototype 属性。Object.prototype 属性表示 Object 的原型对象。 那我们在试试Object.getPrototypeOf()和__proto__的关系
Object.getPrototypeOf(doSomeInstancing);
//
doSomeInstancing.__proto__;// ? true or false
Object.getPrototypeOf(doSomeInstancing) doSomeInstancing.__proto__;某些浏览器内部还是支持__proto__的例如谷歌结论[[Prototype]] 就是 proto 下文还是用 大家熟知的__proto__说道
回过头发现doSomeInstancing.__proto__和doSomething.prototype打印结果是一样的
Object.getPrototypeOf(doSomeInstancing) DoSomething.prototype;
// 所以 Object.getPrototypeOf(doSomeInstancing) doSomeInstancing.proto DoSomething.prototype
那什么是原型链呢
思考一个问题如果访问doSomeInstancing里的一个属性浏览器是怎么做的
浏览器首先会查看doSomeInstancing 中是否存在这个属性如果 doSomeInstancing 不包含属性信息那么浏览器会在 doSomeInstancing 的 __proto__ 中进行查找 (同 doSomething.prototype). 如属性在 doSomeInstancing 的__proto__中查找到则使用 doSomeInstancing 中 __proto__ 的属性。否则如果doSomeInstancing中 __proto__ 不具有该属性则检查doSomeInstancing 的 __proto__ 的 __proto__ 是否具有该属性。默认情况下任何函数的原型属性__proto__都是 window.Object.prototype. 因此通过 doSomeInstancing 的__proto__的 __proto__ ( 同 doSomething.prototype 的 __proto__ (同 Object.prototype)) 来查找要搜索的属性。如果属性不存在 doSomeInstancing 的 __proto__ 的 __proto__ 中那么就会在doSomeInstancing 的 __proto__ 的 __proto__ 的 __proto__ 中查找。然而这里存在个问题doSomeInstancing 的 __proto__ 的 __proto__ 的 __proto__ 其实不存在。因此只有这样在 __proto__ 的整个原型链被查看之后这里没有更多的__proto__浏览器断言该属性不存在并给出属性值为undefined的结论。
找一个属性要顺着原型__proto__一直找下去这时候就会形成一个链路这就是原型链的查找规则而原型链就是这个规则本身。
但是要注意一点__proto__只是提供一种查找规则是非标准的实际指向的还是prototype 原型对象。实际开发中不推荐使用推荐在prototype上操作。
constructor 构造函数
**对象的原型 __ proto __ 和原型对象prototype**里面都有一个属性 constructor 属性 constructor 我们称为构造函数因为它指回构造函数本身。
constructor 主要用于记录该对象引用于哪个构造函数它可以让原型对象重新指向原来的构造函数。
function DoSomething(eat){this.eat eat;
}
var doSomeInstancing new DoSomething(吃);console.log(DoSomething.prototype.constructor);
console.log(doSomeInstancing.__proto__.constructor);FQA
proto、prototype、constructor关系 属性查找机制
当访问一个对象的属性包括方法时首先查找这个对象自身有没有该属性。如果没有就查找它的原型也就是 proto 指向的 prototype 原型对象。如果还没有就查找原型对象的原型Object的原型对象。依此类推一直找到 Object 为止null。proto 对象原型的意义就在于为对象成员查找机制提供一个方向或者说一条路线。
原型链的终点是什么
由于Object是构造函数原型链终点是Object.prototype.proto而Object.prototype.proto null // true所以原型链的终点是null。原型链上的所有原型都是对象所有的对象最终都是由Object构造的而Object.prototype的下一级是Object.prototype.proto。
代码输出
function DoSomething(){
}
DoSomething.prototype.foo bar;var doSomeInstancing new DoSomething();doSomeInstancing.prop some value;// 下面代码输出
console.log(doSomeInstancing.prop: doSomeInstancing.prop); // some value
console.log(doSomeInstancing.foo: doSomeInstancing.foo); // bar
console.log(doSomething.prop: DoSomething.prop); // undefined
console.log(doSomething.foo: DoSomething.foo); // undefined
console.log(doSomething.prototype.prop: DoSomething.prototype.prop); // undefined
console.log(doSomething.prototype.foo: DoSomething.prototype.foo); // barfunction Fn(){var a 12this.getName function(){console.log(private getName)}
}Fn.prototype.getName function (){console.log(public getName)
}var fn new Fn()
var fn1 new Fn()
// 12
console.log(fn.a) // undefined
console.log(fn.getName()) // private getName
// 345
console.log(fn.getName fn1.getName) // false
console.log(fn.__proto__.getName fn1.__proto__.getName) // true
console.log(fn.__proto__.getName Fn.prototype.getName) // true
//67
console.log(fn.hasOwnProperty Object.prototype.hasOwnProperty) // ture
console.log(fn.constructor Fn) // ture new如何实现
创建一个空对象作为将要返回的对象实例。将空对象的原型指向了构造函数的prototype属性。将空对象赋值给构造函数内部的this关键字。开始执行构造函数内部的代码。返回此对象
function _new (fn, ...args) {// 不是一个函数if (typeof fn function) {///创建一个空对象作为将要返回的对象实例。const obj new Object();// 将空对象的原型指向了构造函数的prototype属性。obj.__proto__ fn.prototype;// 将空对象赋值给构造函数内部的this关键字const result fn.apply(obj, args);return result instanceof Object ? result : obj; } else {throw TypeError(not a function);}
}原型的应用
instanceof 如果A instanceof B。判断 B 的 prototype 属性指向的原型对象(B.prototype)是否在对象 A 的原型链上。vue2的eventBus给某个对象加一个公用封装方法
finish各位观众姥爷收藏➕关注追好文不迷路