1.原型
1.1
原型:内存空间复用
1)任何函数都有一个属性prototype 是一个对象 new Object()/{}/{}
2)任何对象都有一个__proto__属性 是创建它的函数的prototype属性
3)任何对象都是函数创建出来的 任何对象都有"类型" (构造函数)
1.2 思想
用函数创建对像,这个创建出来的对象有个原型对象1,又用这个函数创建对象 这个创建出来的对象有个原型对象2,原型对象1和原型对象2是同一个对象。
1.3 案列解析
function fn(){
this.a=20
}
//隐式操作:fn.prototye={}
function fm () {
this.a=30
}
//隐式操作:fm.prototye={fn:{a:20,__proto__:{}}}
//new fn()==>{__proto__:fn.prototye}==>{a:20,__proto__:{}}
fm.prototype.fn=new fm()
var f1=new fm()
//new fm()
//{__proto__:fm.prototype,a:30}==>{__proto__:{fn:{a:20,__proto__:{}}},a:30}
console.log(f1)//写出它的结构(只写a)
//{a:30,__proto__:{fn:{a:20}}}
分析: fm.prototype.fn 给fm函数的原型对象添加一个fn成员 fm.prototype.fn=new fn() fn成员为new fn()---{fn:{a:20,proto:{}},proto:{}}
new fm()----{proto:fm.prototype,a:30}---{proto:{fn:{a:20,proto:{}}},a:30},既f1打印为{a:30,proto:{fn:{a:20}}}
2.构造函数分类
1.自定函数
2.官方提供的函数:Function Object String Number Bloolean Array Date Math
var obj1=new Object()
var arr1=new Array()
3.语法糖
语法糖: 对象直接量 (代码有多种写法时 简便的写法就是语法糖 )
列:
@click="fn" =>onlick="fn()"
obj.age==>obj["age"]
4.原型链案列
1)案例: 自定义构造函数的原型对象也是一个自定义构造函数创建的对象
function Kedou() {
this.life=1
this.tail=1
}
var k1=new Kedou()
function Qingwa () {
this.tui=4
this.yanjing=2
}
Qingwa.prototype=new Kedou()
var q1=new Qingwa()
console.log(q1.life)
k1是不是q1原型对象?
console.log(q1.__proto__==k1)//false
分析:k1不是q1的原型对象
function Element(){
this.width="20px"
this.color="red"
this.fontSize="20px"
}
function Div() {
this.value=123
this.innerHTML="hello"
}
var el=new Element()
el.height="40px"
Div.prototype=el //执行以后 用Div创建的对象有Element创建的对象的功能
var div1=new Div()
div1.className="box"
console.log(div1.value,div1.innerHTML,div1,div1.width)
var div2=new Div()
console.log(div2.value,div2.innerHTML,div2,div2.width)
console.log(div2.className,div2.height,div1.height,div1.className)//und 40px
分析:
5.对象属性的存取及原型的存取
5.1 对象属性的存取
1)obj.a=20 obj对象的原型链上无论有没有a成员的,a一定会添加或更新obj自己的这一层
2)console.log(obj.a) 先取自己的 自己没有就去原型链取 null都没有就得到undefined
3)console.log(obj.x1) 如果x1是原型链上成员:可以取出使用
4)obj.x1=[10,20,40] 如果x1是原型链上的成员或者不是原型链上的成员 都不能修改这个x1属性(因为会把x1属性添加/更新到obj自己上)
5)若x1是原型链上的属性 虽然不能修改 但是可以操作
obj={name:“karen”,x1:{x2:2}}
obj.x1.x2=30
obj.x2.push(123)
5.2 原型的存取
1)构造函数的prototype属性可以操作
2)内置构造函数的prototype不能修改(不能用等号直接赋值) 但是可以操作(可以给原型属性添加成员)
Array.prototype.push = 代码
3)对象的__proto__也可以操作和修改,内置的对象不能修改,若修改则会跳过编译(静默)
var arr=new Array(10,20,40)
arr.__proto__.fn=90
var arr2=[10]
console.log(arr2.fn)
5.3 笔试题练习
function Parent() {
this.a = 1;
this.b = [1, 2, this.a];
this.c = {
demo: 5
};
this.show = function() {
console.log(this.a, this.b, this.c.demo);
}
}
function Child() {
this.a = 2;
this.change = function() {
this.b.push(this.a);
this.a = this.b.length;
this.c.demo = this.a++;
}
}
Child.prototype = new Parent();
//后面的代码用Child函数创建的对象的原型对象是new Parent()
//Child.prototype =O1{a:1,b:[1,2,1],c:{demo:5},show:上面的函数,__proto__:O3{}}
var parent = new Parent();
//parent=O2{a:1,b:[1,2,1],c:{demo:5},show:上面的函数,__proto__:O3{}}
var child1 = new Child();
//child1={a:2,change:上面的函数,__proto__:O1}
var child2 = new Child();
//child2={a:2,change:上面的函数,__proto__:O1}
child1.a = 11; //无论child1的原型链上是否有a成员 都会把a添加/更新到child1自己
上 child1={a:11,change:上面的函数,__proto__:O1}
child2.a = 12;//child2={a:12,change:上面的函数,__proto__:O1}
parent.show(); //console.log(this.a, this.b, this.c.demo);==>parent就是this
也就是O2对象 O2.a=>1 O2.b==>[1,2,1] O2.c.demo==>5
//打印 1 [1,2,1] 5
child1.show(); //show函数是原型对象的方法 child1自己没有 就访问了原型的 但是调
用者(函数内部的this)是child1 ===>console.log(this.a, this.b, this.c.demo);
//this.a==>11 this.b==>自己没有去访问原型的=>[1,2,1] this.c.demo==>自己没有去访问原型的=>5
//打印 11 [1,2,1] 5
child2.show();
//show函数是原型对象的方法 child2自己没有 就访问了原型的
但是调用者(函数内部的this)是child2 ===>console.log(this.a, this.b, this.c.demo);
//this.a==>12 this.b==>自己没有去访问原型的=>[1,2,1] this.c.demo==>自己没有去访问原型的=>5
//打印12 [1,2,1] 5
child1.change();
/*
this是child1
this.b.push(this.a);//b是原型对象的属性 但是这个代码没有修改b 只是操作了b内部的数据
是可以让原型对象内部的数据改变 ,
this.a取值会优先取原型链的最顶层的属性11 ==> 原型对象的数组末尾添加了11
Child.prototype =O1{a:1,b:[1,2,1,11],c:{demo:5},show:上面的函数,__proto__:O3{}}
this.a = this.b.length;
//给child1自己添加/更新 a属性 值为4 child1的原型对象的属性b的长度
child1={a:4,change:上面的函数,__proto__:O1}
this.c.demo = this.a++;
//this.c.demo=先取值4 再把a的值加1
child1={a:5,change:上面的函数,__proto__:O1}
//this.c属性是原型对象的属性 但是没有修改这个属性的情况下 是可以操作其内部的数据的
//因此原型对象的的c属性中的demo属性改为4
Child.prototype =O1{a:1,b:[1,2,1,11],c:{demo:4},show:上面的函数,__proto__:O3{}}
*/
child2.change();
/*
this是child2
this.b.push(this.a);==>同上 b是原型对象的属性 但是这个代码没有修改b
只是操作了b内部的数据是可以让原型对象内部的数据改变
this.a取值会优先取原型链的最顶层的属性12,原型对象的数组末尾添加了12
Child.prototype =O1{a:1,b:[1,2,1,11,12],c:{demo:4},show:上面的函数,__proto__:O3{}}
this.a = this.b.length;
//this.a = 原型对象的b属性的length==>5;
child2={a:5,change:上面的函数,__proto__:O1}
this.c.demo = this.a++;
// this.c.demo=取值5(修改了原型对象) a再加1
child2={a:6,change:上面的函数,__proto__:O1}
Child.prototype =O1{a:1,b:[1,2,1,11,12],c:{demo:5},show:上面的函数,__proto__:O3{}}
*/
parent.show();
//show函数内部的this是parent
//console.log(this.a, this.b, this.c.demo);
//1 [1,2,1] 5
child1.show();
//show函数内部的this是child1
//console.log(this.a, this.b, this.c.demo);
// 5 [1,2,1,11,12] 5 (this.b,this.c都是原型上的)
child2.show();
//show函数内部的this是child2
//console.log(this.a, this.b, this.c.demo);
//6 [1,2,1,11,12] 5 (this.b,this.c都是原型上的)