JS基础 原型与继承
Posted wgchen~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS基础 原型与继承相关的知识,希望对你有一定的参考价值。
阅读目录
原型基础
原型对象
每个对象都有一个原型 prototype
对象,通过函数创建的对象也将拥有这个原型对象。
原型是一个指向对象的指针。
- 可以将原型理解为对象的父亲,对象从原型对象继承来属性
- 原型就是对象除了是某个对象的父母外没有什么特别之处
- 所有函数的原型默认是 Object 的实例,所以可以使用
toString / toValues / isPrototypeOf
等方法的原因。 - 使用原型对象为多个对象共享属性或方法
- 如果对象本身不存在属性或方法将到原型上查找
- 使用原型可以解决,通过构建函数创建对象时复制多个函数造成的内存占用问题
- 原型包含
constructor
属性,指向构造函数 - 对象包含
__proto__
指向他的原型对象
使用数组原型对象的 concat 方法完成连接操作
下例使用的就是数组原型对象的 concat
方法完成的连接操作。
let hd = ["a"];
console.log(hd.concat("b"));
console.log(hd);
默认情况下创建的对象都有原型。
let hd = name: "wgchen" ;
console.log(hd);
以下 x、y 的原型都为元对象 Object,即JS中的根对象
let x = ;
let y = ;
console.log(Object.getPrototypeOf(x) == Object.getPrototypeOf(y)); //true
// Object.getPrototypeOf()方法返回指定对象的原型(即内部属性的值)。[[Prototype]]
创建一个极简对象(纯数据字典对象)没有原型(原型为 null
)
我们也可以创建一个极简对象(纯数据字典对象)没有原型(原型为 null
)
// hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
let hd = name: 3 ;
console.log(hd.hasOwnProperty("name")); // true
let xj = Object.create(null,
name:
value: "wgchen"
);
console.log(xj.hasOwnProperty("name"));
// Uncaught TypeError: xj.hasOwnProperty is not a function
//Object.keys是静态方法,不是原型方法所以是可以使用的
console.log(Object.keys(xj));
console.log(xj);
函数拥有多个原型,prototype 用于实例对象使用,__proto__
用于函数对象使用
function User()
User.__proto__.view = function()
console.log("User function view method");
;
User.view();
User.prototype.show = function()
console.log("wgchen");
;
let hd = new User();
hd.show();
console.log(User.prototype == hd.__proto__);
原型关系分析,与方法继承的示例
let hd = new Object();
hd.name = "wgchen";
Object.prototype.show = function()
console.log("blog");
;
hd.show();
function User()
let xj = new User();
xj.show();
User.show();
使用构造函数创建对象的原型体现
- 构造函数拥有原型
- 创建对象时构造函数把原型赋予对象
function User()
let xj = new User();
console.log(xj.__proto__ == User.prototype); // true
下面使用数组会产生多级继承即原型链
let hd = [];
console.log(hd);
console.log(hd.__proto__ == Array.prototype);
let str = "";
console.log(str.__proto__ == String.prototype);
下面使用 setPrototypeOf
与 getPrototypeOf
获取与设置原型
let hd = ;
let parent = name: "parent" ;
Object.setPrototypeOf(hd, parent);
console.log(hd);
console.log(Object.getPrototypeOf(hd));
使用自定义构造函数创建的对象的原型体现
function User()
let hd = new User();
console.log(hd);
constructor
存在于 prototype
原型中,用于指向构建函数的引用。
function hd()
this.show = function()
return "show method";
;
const obj = new hd();
console.log(obj instanceof hd); //true
const obj2 = new obj.constructor();
console.dir(obj2.show()); //show method
使用对象的 constructor
创建对象
function User(name, age)
this.name = name;
this.age = age;
function createByObject(obj, ...args)
const constructor = Object.getPrototypeOf(obj).constructor;
return new constructor(...args);
let hd = new User("wgchen");
let xj = createByObject(hd, "willem", 12);
console.log(xj);
原型链
通过引用类型的原型,继承另一个引用类型的属性与方法,这就是实现继承的步骤。
使用 Object.setPrototypeOf
可设置对象的原型,下面的示例中继承关系为 obj>hd>cms
。
Object.getPrototypeOf
用于获取一个对象的原型。
let obj =
name: "wgchen"
;
let hd =
web: "blog"
;
let cms =
soft: "willem"
;
//让obj继承hd,即设置obj的原型为hd
Object.setPrototypeOf(obj, hd);
Object.setPrototypeOf(hd, cms);
console.log(obj.web); // blog
console.log(Object.getPrototypeOf(hd) == cms); //true
原型检测
instanceof
检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
function A()
function B()
function C()
const c = new C();
B.prototype = c;
const b = new B();
A.prototype = b;
const a = new A();
console.dir(a instanceof A); //true
console.dir(a instanceof B); //true
console.dir(a instanceof C); //true
console.dir(b instanceof C); //true
console.dir(c instanceof B); //false
使用 isPrototypeOf
检测一个对象是否在另一个对象的原型链中
const a = ;
const b = ;
const c = ;
Object.setPrototypeOf(a, b);
Object.setPrototypeOf(b, c);
console.log(b.isPrototypeOf(a)); //true
console.log(c.isPrototypeOf(a)); //true
console.log(c.isPrototypeOf(b)); //true
属性遍历
使用 in
检测原型链上是否存在属性,使用 hasOwnProperty
只检测当前对象。
let a = url: "blog" ;
let b = name: "wgchen" ;
Object.setPrototypeOf(a, b);
console.log("name" in a); // true
console.log(a.hasOwnProperty("name")); // false
console.log(a.hasOwnProperty("url")); // true
使用 for/in
遍历时同时会遍历原型上的属性如下例
let hd = name: "wgchen" ;
let xj = Object.create(hd,
url:
value: "blog",
/*
属性四种特性之一enumerable:
对象属性是否可通过for-in循环,或Object.keys() 读取
*/
enumerable: true
);
for (const key in xj)
console.log(key);
hasOwnProperty
方法判断对象是否存在属性,而不会查找原型。
所以如果只想遍历对象属性使用以下代码
let hd = name: "wgchen" ;
let xj = Object.create(hd,
url:
value: "blog",
enumerable: true
);
for (const key in xj)
if (xj.hasOwnProperty(key))
console.log(key); // url
借用原型 *
使用 call
或 apply
可以借用其他原型方法完成功能。
下面的 xj 对象不能使用 max 方法,但可以借用 hd 对象的原型方法。
let hd =
data: [1, 2, 3, 4, 5]
;
Object.setPrototypeOf(hd,
max: function()
return this.data.sort((a, b) => b - a)[0];
);
console.log(hd.max()); // 5
let xj =
lessons: js: 100, php: 78, node: 78, linux: 125 ,
get data()
return Object.values(this.lessons);
;
console.log(hd.__proto__.max.apply(xj));// 125
上例中如果方法可以传参,那就可以不在 xj
对象中定义 get
方法了。
let hd =
data: [1, 2, 3, 4, 5]
;
Object.setPrototypeOf(hd,
max: function(data)
return data.sort((a, b) => b - a)[0];
);
console.log(hd.max(hd.data)); // 5
let xj =
lessons: js: 100, php: 78, node: 78, linux: 125
;
console.log(hd.__proto__.max.call(xj, Object.values(xj.lessons))); // 125
因为 Math.max
就是获取最大值的方法,所以代码可以再次优化
let hd =
data: [1, 2, 3, 4, 5]
;
console.log(Math.max.apply(null, Object.values(hd.data))); // 5
let xj =
lessons: js: 100, php: 78, node: 78, linux: 125
;
console.log(Math.max.apply(xj, Object.values(xj.lessons))); // 125
下面是获取设置了 class
属性的按钮,但DOM节点不能直接使用数组的 filter
等方法,但借用数组的原型方法就可以操作了。
<body>
<button message="wgchen" class="red">wgchen but</button>
<button message="blog">blog but</button>
</body>
<script>
let btns = document.querySelectorAll("button");
btns = Array.prototype.filter.call(btns, item =>
return item.hasAttribute("class");
);
</script>
this 不受原型继承影响
this 指向调用属性时使用的是对象。
let hd =
name: "wgchen"
;
let ycc =
name: "willem",
show()
return this.name;
;
hd.__proto__ = ycc;
console.log(hd.show()); // wgchen
原型总结
prototype
函数也是对象,也有原型,函数有 prototype
属性指向他的原型
为构造函数设置的原型指,当使用构造函数创建对象时把这个原型赋予给这个对象
function User(name)
this.name = name;
User.prototype =
show()
return this.name;
;
let xj = new User("wgchen");
console.log(xj.show()); // wgchen
函数默认 prototype
指包含一个属性 constructor
的对象,constructor
指向当前构造函数
function User(name)
this.name = name;
let xj = new User("wgchen"); // User name: 'wgchen'
console.log(xj);
console.log(User.prototype.constructor == User); //true
console.log(xj以上是关于JS基础 原型与继承的主要内容,如果未能解决你的问题,请参考以下文章