原型与继承前置看这里
原型
原型都了解了,但是不是所有对象都有对象原型
let obj1 = {}console.log(obj1)let obj2 = Object.create(null, {name: {value: '荷叶饭'}})console.log(obj2)
obj2为什么没有对象原型?obj2是完全的数据字典对象,没有对象的关系
但是这种对象用到的地方很少
原型方法和对象方法的优先级
一句话,就是自己有方法就不要原型的方法,自己没有的才会向上检索
函数拥有多个对象原型
原型链:
这是我自己画的图,其实和之前看品客老师那张图是一样的:
js里万物皆对象,所以其他类型也有原型关系:
let arr = []; // new Arrayconsole.log(arr.__proto__ == Array.prototype);let str = ""; //new Stringconsole.log(str.__proto__ == String.prototype);let bool = true;console.log(bool.__proto__ == Boolean.prototype);let reg = /a/i; // new RegExpconsole.log(reg.__proto__ == RegExp.prototype);let obj = {};console.log(obj.__proto__ == Object.prototype);
很多关于原型的方法
改变对象的原型
使用Object.setPrototypeOf(son, parent)
let son = { name: "son" };let parent = {name: "parent",show() {console.log("parent method:" + this.name);}};// console.log(hd.__proto__ == Object.prototype)//trueObject.setPrototypeOf(son, parent)//设置son的原型为parentconsole.log(Object.getPrototypeOf(son))//验证,原型确实被设置为了parent
也可以在属性里改变
constructor学过了,这里就不说了
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
function A() { }function B() { }function C() { }let c = new C();B.prototype = c;let b = new B();A.prototype = b;let a = new A();console.log(a instanceof A);//trueconsole.log(a instanceof C);//trueconsole.log(a instanceof C);//trueconsole.log(b instanceof A);//false
小在左,大在右,才为true
isPrototypeOf()
方法用于检查一个对象是否存在于另一个对象的原型链中:
let a = {}let b = {}let c = {}Object.setPrototypeOf(b, c)//设置b的原型为cObject.setPrototypeOf(a, b)//设置a的原型为bconsole.log(b.isPrototypeOf(a))//b在不在a的原型链里,trueconsole.log(c.isPrototypeOf(b))//trueconsole.log(c.isPrototypeOf(a))//true
hasOwnProperty()
方法返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性。
in操作符会检测整条原型链
let a = { name1: "我是a" };let b = { name: "我是b" };Object.setPrototypeOf(a, b);console.log(a.hasOwnProperty("name"))//falseconsole.log("name" in a)//truefor (const key in a) {if (a.hasOwnProperty(key)) {console.log(a[key])//我是a}}
使用call或apply借用原型链
自己的对象里没有某个属性,可以通过call或apply改变当前的this,来获取新this的原型链的属性或方法,算一个小技巧吧:
let hd = {data: [1, 2, 3, 34, 5, 7]};Object.setPrototypeOf(hd, {max(data) {return data.sort((a, b) => b - a)[0];}})let xj = {lessons: { js: 87, php: 63, node: 99, linux: 88 }};console.log(hd.max.call(null, Object.values(xj.lessons)))//99,相当于用hd的原型里的方法求xj里的最大值
这里也区分一下call和apply,call可以传分散的参数,apply传数组,用math方法
let arr = [1, 3, 43, 4];console.log(Math.max(...arr));let hd = {data: [1, 2, 3, 34, 5, 7]};console.log(Math.max.call(null, ...hd.data))//使用.语法展开let xj = {lessons: { js: 87, php: 63, node: 99, linux: 88 }};console.log(Math.max.apply(null, Object.values(xj.lessons)))//可以传数组
Dom节点借用数组的过滤操作
dom节点没有过滤操作,但是数组有,所以可以借助数组方法:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>后盾人</title></head><body><button message="后盾人" class="red">后盾人</button><button message="hdcms">hdcms</button></body><script>let arr = [1, 3, 43];let res = arr.filter(item => {return item > 39;});// console.dir();console.log(res);let btns = document.querySelectorAll("button");btns = [].filter.call(btns, item => {//借用数组操作return item.hasAttribute("class");});console.log(btns);</script>
</html>