JavaScript高级,ES6 笔记 第三天
构造函数会造成内存浪费的问题
这里创造了两个实例,对于sing都会创造一部分内存,然而sing内部的函数是一样的,我们希望两者指向的是同一个内存区域 ,即指向同一个function();
原型prototype
<script>
function star(uname,age){
this.uname = uname
this.age = age
}
star.prototype.sing = function(){
console.log(123);
}
let ldh = new star('ldh',55);
let zxy = new star('zxy',67);
ldh.sing()//123
zxy.sing()//123
console.log(ldh.sing == zxy.sing);//true
</script>
也就是说将sing定义到prototype中可以使得所有对象的sing都指向同一块内存‘
公共属性写道构造函数里面
公共方法写道原型对象上
自己创造对象方法
求最大值
Array.prototype.max = function(){
// return Math.max(...this)
let max = this[0];
for (let i = 1;i<arr.length;i++){
if(this[i]>max){
max = this[i]
}
}
return max;
}
arr = new Array(2,3,4,1,5,66,7);
console.log(arr.max());
求和
Array.prototype.sum = function(){
return this.reduce((prev,item)=>prev+item,0)
}
arr = new Array(2,3,4,1,5,66,7);
console.log(arr.sum());
constructor
也就是说可以指向原型的父辈构造函数
function star(name){
this.name = name;
}
console.log(star.prototype.constructor == star);//true
当给原型幅值时:
<script>
function star(name){
}
star.prototype = {
sing:function(){
console.log('aaa');
},
dance:function(){
console.log('bbb');
}
}
console.log(star.prototype.constructor == star);//false
</script>
就不能指向构造函数了,因为对原型进行了赋值操作,故应该将constructor重新指回构造函数
<script>
function star(name){
}
star.prototype = {
constructor:star,
sing:function(){
console.log('aaa');
},
dance:function(){
console.log('bbb');
}
}
console.log(star.prototype.constructor == star);//true
</script>
</body>
对象原型_proto_
也就是说所有对象都有对象原型__proto__(也写作[[prototype]]),指向prototype,其是只读的。
对象原型也有constructor,指向构造函数
<script>
function star(name){
}
let ldh = new star()
console.log(ldh.__proto__.constructor == star );//true
</script>
原型继承
<script>
const person = {
head: 1,
arms: 2
}
function woman(){
}
woman.prototype = person
woman.prototype.constructor = woman
const red = new woman;
console.log(red.arms);//2
</script>
也就是构造函数的原型继承person对象,叫做原型继承
遇到的问题
<script>
const person = {
head: 1,
arms: 2
}
function woman(){}
function man(){}
woman.prototype = person
woman.prototype.constructor = woman
woman.prototype.baby = function(){
console.log('baby');
}
man.prototype = person
man.prototype.constructor = man
const red = new woman;
console.log(red);//2
const black = new man;
console.log(black);
</script>
主要是给woman man构造函数都继承了person对象
然后给woman添加了一个baby方法
结果发现,red 和 black都有baby方法
原因是 woman和man的.prototype都指向了同一个地址,既person,当我改变woman.prototype时,实际上也就把person改变了
解决方法:将person换成构造函数
<script>
function person (){
this.head = 1 ;
this.arms = 2
}
function woman(){}
function man(){}
woman.prototype = new person()
woman.prototype.constructor = woman
woman.prototype.baby = function(){
console.log('baby');
}
man.prototype = new person()
man.prototype.constructor = man
const red = new woman;
console.log(red);//2
const black = new man;
console.log(black);
</script>
这样就可以保证,woman和man的.prototype指向不同的地址
原型链
对于具体对象 ldh,其ldh.__proto__指向原型对象
function person(){}
const ldh = new person();
console.log(ldh.__proto__ == person.prototype);//true
而原型对象也有对象原型,既person.prototype.__proto__ 存在
console.log(person.prototype.__proto__ == Object.prototype);//true
同理 ,也存在Object.prototype.__proto__,为null
console.log(Object.prototype.__proto__);//null
那么这几个__proto__连起来,就是原型链
相当于原型链提供了一个查找的方向,可以一层一层查找方法或属性所在的位置
例如数组的map方法,其实是写在Array.prototype.map(),但是因为有原型链的存在,所以普通的数组对象也可以使用这个方法
let sss = [123,22,33,44];
let sae = sss.map(item=>item+3)
console.log(sae);
instanceof
function person(){}
const ldh = new person();
console.log(ldh.__proto__ == person.prototype);//true
console.log(Object.prototype.__proto__);//null
console.log(ldh instanceof person);//true
console.log(ldh instanceof Object);//true
console.log(ldh instanceof Array);//false
小案例
目的:按下按钮弹出提示框(采用构造函数的方法来做)
先给CSS
<style>
.modal {
width: 300px;
min-height: 100px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
border-radius: 4px;
position: fixed;
z-index: 999;
left: 50%;
top: 50%;
transform: translate3d(-50%, -50%, 0);
background-color: #fff;
}
.modal .header {
line-height: 40px;
padding: 0 10px;
position: relative;
font-size: 20px;
}
.modal .header i {
font-style: normal;
color: #999;
position: absolute;
right: 15px;
top: -2px;
cursor: pointer;
}
.modal .body {
text-align: center;
padding: 10px;
}
.modal .footer {
display: flex;
justify-content: flex-end;
padding: 10px;
}
.modal .footer a {
padding: 3px 8px;
background: #ccc;
text-decoration: none;
color: #fff;
border-radius: 2px;
margin-right: 10px;
font-size: 14px;
}
.modal .footer a.submit {
background-color: #369;
}
</style>
具体解释看代码,
<body>
<button id="delete">删除</button>
<button id="login">登录</button>
<script>
//先定义一个构造函数,表示这个提示框,里面有两个参数,即标题和内容,这个地方需要创造一个div,并按照格式写入
function model(header = '', body = '') {
this.header = header;
this.body = body;
this.box = document.createElement('div')
this.box.className = 'model';
this.box.innerHTML = ` <div class="modal">
<div class="header">${this.header} <i>x</i></div>
<div class="body">${this.body}</div>
</div>`
}
//给构造函数添加关闭的方法,就是之间移除之前创造的div
model.prototype.close = function(){
document.body.removeChild(this.box)
}
//给构造函数添加打开的方法,先加判断,页面中没有提示框才能添加提示框
//添加子节点box
//将box中的x与close函数绑定
model.prototype.open = function(){
if(!document.querySelector('.model')){
document.body.appendChild(this.box)
this.box.querySelector('i').addEventListener('click',()=>{
this.close()
})
}
}
//实例化
document.querySelector('#delete').addEventListener('click',function(){
const m = new model('温馨提示','你没有权限删除');
m.open()
})
</script>
</body>