龙港做网站店铺,如何选择丹阳网站建设,天元建设集团有限公司第六建筑工程公司,美工培训原型和原型链
在js中#xff0c;所有的变量都有原型#xff0c;原型也可以有原型#xff0c;原型最终都指向Object
什么是原型
在js中#xff0c;一个变量被创建出来#xff0c;它就会被绑定一个原型#xff1b;比如说#xff0c;任何一个变量都可以使用console.log打…原型和原型链
在js中所有的变量都有原型原型也可以有原型原型最终都指向Object
什么是原型
在js中一个变量被创建出来它就会被绑定一个原型比如说任何一个变量都可以使用console.log打印这里是调用了它的toString方法而变量被创建后可能并没有设置toString方法但是它任然可以打印这就从原型中获取的toString方法 所以可以得到第一点原型可以提供方法给实例的变量
原型也是一个对象或者说对象可以作为原型并赋值给其他变量这样对象成为了变量的原型而对象本身也有原型此时就形成了 ‘链’ 同样的这个变量也是一个对象他也可以作为其他变量的原型这样‘链’就变得更长了但是所有的链都有一个最终指向root终点--- ObjectObejct是最原始的对象它包含了所有js变量都共享的方法它不再有原型属性[[prototype]], 所以在js中一切皆对象中的对象就是指的继承自Object
这里可以总结一下 原型是一个对象它可以向继承了自身的变量提供方法属性变量都拥有原型也可以成为原型循环下去可以形成‘链’链的最顶端是Object对象它提供了最基本的方法 js通过原型来复用通用的方法和属性这样极大的减少了变量创建的成本减少了内存支出原型的方法属性都存储在原型上变量中不会复制过来占用内存也不必每个对象都去书写基本的方法
tips
原型链就前面说到的 变量获得原型原型又有原型变量又可以作为原型这样就形成了‘链’链的最外层底层拥有最多的方法继承了原型链上所有原型的方法和属性
prototype
在 JavaScript 中对象有一个特殊的隐藏属性 [[Prototype]]如规范中所命名的它要么为 null要么就是对另一个对象的引用。当我们从 object 中读取一个缺失的属性时JavaScript 会自动从原型中获取该属性。这就是继承object也可以从中借用方法
prototype不能在变量中被直接引用通常没有办法遍历或者读取这个属性所以它在控制台的名称有些特殊使用[[ ]]引用但是可以直接去调用它里面的方法当你使用变量中不存在的属性或者方法此时会自动向原型中寻找对应的属性方法并调用若原型链中没有则返回undefined
但是也有特例在构造函数中可以给构造的实例添加原型属性或方法
__proto__
这是一个过时的属性现在只能在浏览器中使用它的作用就是指向prototype给原型添加属性或方法这样添加的原型属性或方法会被遍历出来Object.keys,for in,
let animal {eats: true
};
let rabbit {jumps: true
};rabbit.__proto__ animal; // 设置 rabbit.[[Prototype]] animal 注意__proto__ 与内部的 [[Prototype]] 不一样。__proto__ 是 [[Prototype]] 的getter/setter获取和设置原型可以使用函数 Object.getPrototypeOf/Object.setPrototypeOf 来替代 __proto__ 去 get/set 原型 new
当使用 new 关键字调用函数时该函数将被用作构造函数。new 将执行以下操作 创建一个空的简单 JavaScript 对象作为实例。如果构造函数的 prototype 属性是一个对象则将实例的 原型[[Prototype]] 指向构造函数的 prototype 属性否则实例将保持为一个普通对象其 [[Prototype]]为 Object.prototype, 因此通过构造函数创建的所有实例都可以访问添加到构造函数 prototype 属性中的属性/对象。使用给定参数执行构造函数并将this指向实例如果构造函数返回非原始值则该返回值成为整个 new 表达式的结果。否则如果构造函数未返回任何值或返回了一个原始值则返回实例。通常构造函数不返回值但可以选择返回值以覆盖正常的对象创建过程。 new的关键点在于它新建了一个实例对象同时引入了原型改变了构造函数的this指向让实例对象成为了这个构造函数的构造结果
class
class是es6新增的语法糖它简化了js中构造类的步骤隐去了对原型的操作根本上还是原型的操作js中的类是基于原型的使用原型达到继承的效果
以下使用原型prototype和类class构建一个相同的类
prototype.js
// 使用原型构造一个P类// 构造器大写开头规范不强制
function P (x,y){// this指向实例此时this不生效构造实例后指向实例this.x x;this.y y;// 实例方法,此处的this指向实例,可以使用实例的属性this.getXY (){return [this.x,this.y]}
}// 实例方法此处的this指向windows不能使用实例的属性
P.prototype.getPName (){return P.name
}// 实例属性
P.prototype.desc 2维坐标//类方法/静态方法
P.getP (p1,p2){return [p1.getXY(),p2.getXY()]
}// 类属性/静态属性
P.des 坐标
class.js
// 使用class构造一个P类class P{//构造器constructor(x,y){this.x x;this.y y;}// 实例属性desc 2维坐标// 实例方法getXY(){return [this.x,this.y]}getPName(){return P.name}// 静态属性static des 坐标// 静态方法static getP(p1,p2){return [p1.getXY(),p2.getXY()]}}
很明显class的用法更加整体化但实际上这两种的写法效果是完成相同的
可以使用同一串代码来实例化这个类P
!DOCTYPE html
html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleprototype,class/title
/headbodyscript srcclass.js/script!-- script srcprototype.js/script --script// new关键字新建一个对象原型指向类获得构造器中的this指向let p new P(1, 2);console.log(p);console.log(p.x);console.log(p.y);console.log(p.desc);console.log(p.getXY());console.log(p.getPName());console.log(P.getP(p, p));console.log(P.des);/script
/body/html 实现的效果是一致的方法上略有不同对于类的构造关键在于this的指向问题属性和方法是挂在类名下的还是挂在实例下的需要区分开
挂在类下的属性方法被称为类方法属性或者静态方法属性通过类名引用Math.max
挂在实例下的属性方法被称为实例方法属性通过实例引用(arr.push)
总结
在 JavaScript 中所有的对象都有一个隐藏的 [[Prototype]] 属性它要么是另一个对象要么就是 null。通过 [[Prototype]] 引用的对象被称为“原型”。prototype 属性仅当设置在一个构造函数上并通过 new 调用时才具有这种特殊的影响。在常规对象上prototype 会被当成是一个普通的属性名所以变量都通过原型/原型链使用共享的方法即自身不存在从原型/原型链中借用类的使用要区分实例和静态类哪些方法属性在类名下哪些方法属性在实例下