原型链自定义设置# 原型链的设置可以通过Object.creative , __proto__, Object.setProperty三种方法
Object.creative ()# 说明: 该方法只能设置原型链,而不能获取
1
2
3
4
let a1 = { name : 'a1' }
let b1 = Object . create ( a1 )
b1 . name = 'b1'
console . log ( b1 );
Object.creative()为创建对象的方法,第一个参数为其原型对象,第二个参数为其默认属性,这些属性默认是不可写,不可遍历,不可修改的
1
2
3
4
5
6
7
let b = Object . create ( null ,{
a : { value : 'ohh' , enumerable : true },
b : { value : 'jqf' },
})
console . log ( Object . getOwnPropertyDescriptors ( b ));
//a: {value: "ohh", writable: false, enumerable: true, configurable: false}
//b: {value: "jqf", writable: false, enumerable: false, configurable: false}
__proto__# 说明: 能设置,能获取,实质上是setter,getter
1
2
3
4
5
let a2 = { name : 'a2' }
let b2 = { name : 'b2' }
a2 . __ proto__ = b2
console . log ( a2 );
console . log ( a2 . __ proto__ ); //{name: "b2"}
关于__proto__是setter,getter?
1
2
3
let a = Object . prototype
console . log ( Object . getOwnPropertyDescriptor ( a , '__proto__' ));
//可以看到'__proto__'的属性描述中有set,get
Object.setProperty# 1
2
3
4
5
let a3 = { name : 'a3' }
let b3 = { name : 'b3' }
Object . setPrototypeOf ( a3 , b3 )
console . log ( a3 );
console . log ( Object . getPrototypeOf ( a3 )); //b3
原型链示意图# 修改_20200904114048
关于检测# 原型链检测# 👉 instanceof
说明: 检测a的原型链上有无A的原型(A.prototype)=>构造函数
1
2
3
function A () {}
let a = new A ()
console . log ( a instanceof A ); //true
👉 isPrototypeOf
说明: 检测b的原型链上有无c对象=>对象
1
2
3
4
5
let b = { name : 'b' }
let c = { name : 'c' }
Object . setPrototypeOf ( b , c )
console . log ( c . isPrototypeOf ( b )); //true
属性检测# 👉 in
说明: 检测本对象及其原型链有无指定属性
👉 hasOwnProperty
说明: 只是检测本对象有无指定属性
1
2
3
4
5
6
7
let a = { name : 'jqf' }
let b = { age : 19 }
Object . setPrototypeOf ( a , b )
console . log ( "age" in a ); //true
console . log ( a . hasOwnProperty ( "age" )); //false
使用for循环时,加上判断是否为本身的key,以免遍历继承与父级的key
1
2
3
4
5
6
7
8
9
10
11
for ( const key in a ) {
console . log ( 'non-if:' + key );
if ( a . hasOwnProperty ( key )){
console . log ( 'if-' + key );
}
}
/*Output
non-if:name
if:name
non-if:age
*/
关于继承# 构造函数# 1
2
3
4
5
6
7
8
9
function User () {
this . name = 'User'
}
User . prototype . show = function () {
console . warn ( 'show method' );
}
function Admin () {
this . name = 'Admin'
}
说明: User 和 Admin分别为两个不相干的构造函数。如果想在Admin的实例化对象能用到User.prototype的方法(prototype为一个对象,其中含有对应构造函数的方法),让Admin.prototype的上级为User.prototype,这样Admin.prototype中,就能用User.prototype中的方法了,简而言之,就是修改子类Admin.prototype 的原型链,使其父级为User.prototype
注意:构造函数中的方法一般都定义在其原型prototype对象中 ,这样,当这个构造函数实例化的时候,不会重新拷贝出来定义在构造函数中的方法,造成不必要的资源浪费,切记!用对象的方法定义构造函数的prototype之后,必须加上constructor属性
1
2
3
4
5
6
7
8
9
10
function Animation () {}
Animation . prototype = {
constructor : Animation , //修改其构造函数!!!
show : function () {
this . style . display = 'block'
},
hide : function () {
this . style . display = 'none'
}
}
开始继承# 1
2
3
4
5
6
7
8
9
10
//__proto__方法/Object.create()方法/Object.setPrototypeOf()方法
Object . setPrototypeOf ( Admin . prototype , User . prototype )
Object . defineProperty ( Admin . prototype , 'constructor' , {
value : Admin ,
enumerable : false
})
Admin . prototype . info = function () {
console . log ( 'Admin' );
}
完成继承# 1
2
3
4
5
let _ admin = new Admin ()
_ admin . show () //show method
_ admin . info () //Admin
console . log ( _ admin . __ proto__ . constructor === Admin ) //true
//实例化的对象可以调用Admin中的方法,也可以用User中的方法
图示
继承的图示
继承函数封装# 1
2
3
4
5
6
7
8
9
10
11
12
/**
* 下级继承上级构造函数
* @param{Function}sub 下级函数
* @param{Function}sup 上级函数
*/
function inherit ( sub , sup ) {
Object . setPrototypeOf ( sub . prototype , sup . prototype )
Object . defineProperty ( sub . prototype , 'constructor' , {
value : sub ,
enumerable : false
})
}
对象合并实现多继承# Javascript 中一个构造函数无法继承多个基函数的方法,即多继承 ,如果都采用构造函数的方式,就只能一层层往上继承,才能做到多继承的效果,但是这样写显然会存在很多问题。于是想到,可以把一些方法写成对象的形式,然后在继承的prototype中合并,这样,就能分门别类地实现按需多继承
方法对象及基函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const Request = {
ajax : function () {
return '请求后台中....'
}
}
const Address = { getAddress : _ => '获取地址中....' }
const Access = { getAccess : _ => '获取权限中....' }
const Info = {
__ proto__ : Request ,
getMore () {
//super=this.__proto__
console . log ( super . ajax (), '获取更多信息中...' );
}
}
function User ( name , age ) {
this . name = name
this . age = age
}
User . prototype . show = function () {
console . log ( this . name , this . age )
}
继承:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*管理员构造函数*/
function Admin ( name , age ) {
User . call ( this , name , age )
}
inherit ( Admin , User )
Object . assign ( Admin . prototype , Access , Request , Info ) //使用哪些合并哪些
let a = new Admin ( 'jqf' , 19 )
a . show ()
console . log ( a . getAccess ());
a . getMore ()
/*会员构造函数*/
function Member ( name , age ) {
User . call ( this , name , age )
}
inherit ( Member , User )
Object . assign ( Member . prototype , Access , Address )
let b = new Member ( 'fin' , 18 )
b . show ()
console . log ( b . getAccess ());
console . log ( b . getAddress ());
说明:
评论
WALINEdocs/COMMENTS.md。