1.没有原型的对象创建
let obj = Object.create(null, {
name: '张三'
})
2.设置和查询原型
Object.setPrototypeOf() 设置原型
Object.getPrototypeOf() 查询原型
let obj = {
name: '张三'
}
let obj2 = {
name: '李四',
show () {
return `名字叫:${this.name}`
}
}
Object.setPrototypeOf(obj, obj2)
console.log(obj.show()) //名字叫: 张三
console.log(obj2.show()) //名字叫: 李四
console.log(Object.getPrototypeOf(obj)) //obj2
3.constructor
constructor 属性返回对象的构造函数
function Fun () {}
console.dir(Fun.prototype.constructor === Fun) //true
4.利用constructor来调用其他对象
function User (name) {
this.name = name
}
let user1 = new User('张三')
function createObj (obj, name) {
const constructor = Object.getPrototypeOf(obj).constructor
return new constructor (name)
}
let user2 = createObj(user1, '李四')
console.log(user2)
5.原型检测之instanceof
判断当前对象是不是某个构造函数的实例
晚辈在前,长辈在后
function A () {}
function B () {}
let b = new B()
A.prototype = b
let a = new A()
console.log(a instanceof B) //true
6.原型检测之isPrototypeOf
判断当前对象是否是某一对象的原型链中
长辈在前,晚辈在后
let A = {}
let B = {}
let C = {}
Object.setPrototypeOf(B, C)
Object.setPrototypeOf(A, B)
console.log(C.isPrototypeOf(A)) //true
7.原型检测之hasOwnProperty
判断当前属性是否单独属于某个对象
在for in中会遍历所有原型,所以可以使用hasOwnProperty来限制遍历范围
let A = {
name: '张三'
}
let B = {
age: 18
}
Object.setPrototypeOf(B, A)
for (const key in A) {
if (A.hasOwnProperty(key)) {
console.log(key) //name
}
}
8.apply或者call来借用原型
let obj = {
data: [1,2,3,4,5]
}
Object.setPrototypeOf(obj, {
max () {
return this.data.sort((a,b) => b - a)[0]
}
})
console.log(obj.max())
let hc = {
lessons: {
html: 10,
css: 20,
js: 0,
node: 70,
vue: 50
},
//访问器,创造一个data
get data (){
return Object.values(this.lessons)
}
}
console.log(obj.max.apply(hc))
9.__proto__其实是访问器,不是属性
10.改变构造函数不是继承,这样会把原先的原型丢掉
11.真正的继承是通过改变原型
function GetName () {}
function Fun () {}
Fun.prototype.showName = function () {
console.log(this.name)
}
Fun.prototype.__proto__ = GetName.prototype
let fun = new Fun()
fun.name = '张三'
fun.showName()
12.使用父类构造函数初始化属性
function User (name, age) {
this.name = name
this.age = age
}
User.prototype.show = function () {
console.log(this.name, this.age)
}
function Admin (...args) {
User.apply(this, args)
}
Admin.prototype.__proto__ = User.prototype
let zs = new Admin('张三', 18)
zs.show()
13.使用工厂函数来封装继承
function extend (sub, sup) {
sup.prototype.__proto__ = sub.prototype
}
function Access () {}
function User () {}
function Admin () {}
function Member () {}
extend(Access, User)
extend(User, Admin)
extend(Admin, Member)
Access.prototype.show = function () {
console.log('show')
}
User.prototype.run = function () {
console.log('run')
}
let user = new User()
let member = new Member()
user.show()
member.run()
14.mixin混合功能, 就是定义一些功能的对象,然后把对象的方法复制到目标的原型上面,就达到了一个继承但可以使用多个功能的目标
如果使用其他继承方法会导致实现多继承会很混乱,本没有关系的两个对象就因为要使用其中一个的方法就强行继承,这样不仅麻烦,而且难以维护。
这种定义功能对象的方法就好比用了钱还不用叫爸爸,超爽
function User (name, age) {
this.name = name
this.age = age
}
User.prototype.show = function () {
console.log('老继承'+this.name)
}
const Ajax = {
ajax () {
console.log('新继承'+this.age)
}
}
function Admin (...args) {
User.apply(this, args)
}
Admin.prototype.__proto__ = User.prototype
console.log(Admin.prototype)
let zs = new Admin('张三', 18)
Object.assign(Admin.prototype, Ajax)
zs.show()
zs.ajax()
15.在功能类中可以使用super关键字来代表this.proto
16.运用原型功能来完成选项卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.tabs{
display: flex;
}
.tabs a{
width: 80px;
height: 30px;
text-align: center;
text-decoration: none;
color: black;
}
.tabs a:nth-child(1){
background-color: #e67e22;
}
.tabs a:nth-child(2){
background-color: #95a5a6;
}
.color{
background-color: brown;
width: 500px;
height: 300px;
font-size: 50px;
}
.hide{
display: none;
}
</style>
</head>
<body>
<div class="tabs">
<a href="#">选项一</a>
<a href="#">选项二</a>
</div>
<div class="color">
<section class="hide">1</section>
<section>2</section>
</div>
<script>
// 继承
function extend (sub, sup) {
sup.prototype.__proto__ = sub.prototype
}
//颜色功能模块
function Animation () {}
Animation.prototype.show = function () {
this.style.display = "block"
}
Animation.prototype.hide = function () {
this.style.display = "none"
}
Animation.prototype.backColor = function (color) {
this.style.background = color
}
//找到dom
function Tab (args) {
args = Object.assign(
{
el: null,
link: 'a',
section: 'section',
callback: null
},
args
)
this.tab = document.querySelector(args['el'])
this.links = document.querySelectorAll(args['link'])
this.sections = document.querySelectorAll(args['section'])
this.callback = args['callback']
}
extend(Animation, Tab)
//点击后改变颜色和显示
Tab.prototype.action = function (i) {
this.backColor.call(this.links[i], "#e67e22")
this.show.call(this.sections[i])
}
//重置颜色
Tab.prototype.reset = function () {
this.links.forEach ((el, i) => {
this.backColor.call(this.links[i], '#95a5a6')
this.hide.call(this.sections[i])
})
}
//运行
Tab.prototype.run = function () {
this.bindEvent()
// 默认第一次显示第一个
this.reset()
this.action(0)
}
//点击事件
Tab.prototype.bindEvent = function () {
this.links.forEach((el, i) => {
el.addEventListener('click', ()=>{
//先重置颜色然后改变目标颜色
this.reset()
this.action(i)
if(this.callback) this.callback()
})
}
)
}
new Tab({
el: '.tabs',
link: 'a',
section: 'section',
callback () {
console.log('123')
}
}).run()
</script>
</body>
</html>