JavaScript 面向对象(五)原型链
5. 原型链
prototype 原型
'每一个构造函数都有一个属性叫做prototype,指向一个对象,'
当这个构造函数被new 的时候,它的每一个实例 (即将生成的对象)的__proto__属性,也指向这个对象
function User() {
console.log(this);
this.name = 'whh'; //即将生成的对象
this.age = 18;
}
var whh =new User();
console.log(whh); //whh这个对象
User {}
age: 18
name: "whh"
__proto__: Object
constructor: ƒ User()
arguments: null
caller: null
length: 0
name: "User"
prototype: {constructor: ƒ},
constructor: ƒ User()
__proto__: Object
__proto__: ƒ ()
apply: ƒ apply()
arguments: (...)
bind: ƒ bind()
call: ƒ call()
caller: (...)
constructor: ƒ Function()
length: 0
name: ""
toString: ƒ toString()
Symbol(Symbol.hasInstance): ƒ [Symbol.hasInstance]()
get arguments: ƒ ()
set arguments: ƒ ()
get caller: ƒ ()
set caller: ƒ ()
__proto__: Object
[[FunctionLocation]]: VM1753:1
[[Scopes]]: Scopes[1]
__proto__: Object
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
每个'函数天生都有prototype属性,指向一个空对象, prototype属性的值是一个对象',也就是说,
我们不需要定义这个prototype属性,任何一个函数只要写出来,它就拥有了prototype属性,
这个属性对它自己而言没有任何意义!它的唯一意义是儿子们 (即将生成的对象)的指明灯!
'构造函数的 prototype属性 指向谁,它new出来的儿子的__proto__属性就指向谁''
function People(name,age,sex) {
this.name =name;
this.age =age;
this.sex =sex;
}
var ming =new People('ming',12,'nan');
console.log(People.prototype===ming.__proto__); //true
console.log(whh.__proto__); //whh这个对象
console.log(User.prototype);//或者也是一样的

'称 People.prototype是People构造函数的 “原型”,People.prototype是ming的 “原型对象”'
5.1
__proto__是神器,有原型链查找功能,当'ming身上没有某个属性'的时候,
'系统会沿着ming的属性__proto__去寻找它的原型对象身上有没有这个属性。''
5.2构造函数的prototype指向谁,new 出来的玩意儿的__proto__就指向谁!!!
这个__proto__有'原型链查找功能''
function People(name,age,sex) {
this.name =name;
this.age =age;
this.sex =sex;
}
People.prototype ={
"teacher":"kao",
"sada":12,
}
var ming =new People('ming',12,'nan');
alert(ming.teacher); //kao
alert(ming['teacher']); //kao
People.prototype=Math; //Math所属对象None
var ming =new People('ming',12,'nan');
alert(ming.random());
ming身上虽然没有random属性,但是小明的__proto__身上有这个属性,
所以ming能够打点调用random属性。
5.3在原型上定义方法
刚才知道如果'把函数写在构造函数里面',就相当于'定义在了对象上',
'此时函数会产生多个不用的副本,影响程序效率,''
此时可以把函数'定义在构造函数的原型'上,
这样所有new出的东西, __proto__就会指向这个对象,从而能够使用这个方法。
function People(name,age,sex) {
this.name =name;
this.age =age;
this.sex =sex;
}
People.prototype.funName=function () { //important
console.log(this);
console.log("woshi:"+this.name+"!nianling:"+this.age);
};
var ming =new People('ming',12,'nan');
var hong =new People('hong',13,'nv');
console.log(ming.funName());
console.log(ming.funName==hong.funName); //true
console.log(ming.funName);
People {name: "ming", age: 12, sex: "nan"}
age: 12
name: "ming"
sex: "nan"
__proto__:
funName: ƒ ()
constructor: ƒ People(name,age,sex)
__proto__: Object
woshi:ming!nianling:12,
VM2101:1 ƒ () {console.log(this);
console.log("woshi:"+this.name+"!nianling:"+this.age);
}
5.4构造函数和实例的关系
构造函数:抽象,定义的是一类对象应该具有什么属性,什么方法, 描述规则,描述蓝图。
实例:具体,根据规则、蓝图创建的一个个具体的实例,它能拥有属性,并且能调用方法。
构造函数中,我们用prototype来定义方法,
'定义的是构造函数的 实例 的方法',不是构造函数的方法。
<input type="button" value="为所有🐕吃饭" id="btn">
<script type="text/javascript">
var dogArr=[];
function Dog(name,w) {
console.log(this);
/* Dog {}
name: "bai",
w: 100,
__proto__: Object
*/
this.name =name;
this.w =w;
dogArr.push(this);
}
Dog.prototype.eat=function () { //important
console.log(this);
// console.log("woshi:"+this.name+"!nianling:"+this.age);
this.w +=10;
};
var bai =new Dog('bai',100);
console.log(bai);
/*
Dog {name: "bai", w: 100}
name: "bai"
w: 100
__proto__: Object
*/
var hei =new Dog('hei',90);
document.getElementById('btn').onclick=function () {
for(var i=0 ; i<dogArr.length ; i++){
dogArr[i].eat();
console.log(dogArr[i].name + ':' +dogArr[i].w);
}
} //加引号
</script>


浙公网安备 33010602011771号