JS原型
原型(对象属性)
- Javascript规定,每一个函数都有一个prototype对象属性,指向另一个对象(原型链上面的)。(prototype指向的是一个对象)
- prototype(对象属性)的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变(公用)的属性和方法,直接定义在prototype对象属性上。
- prototype就是调用构造函数所创建的那个实例对象的原型(proto)。(说明原型是相对的,讲谁是谁的原型)
- prototype可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中
- 摘自链接:https://www.jianshu.com/p/72156bc03ac1
给原型添加属性和方法
1、创建一个构造器函数
function Gadget(name,color){
this.name = name;
this.color = color;
this.whatAreYou = function(){
return 'I am a '+this.color+' ' + this.name;
};
}
2、给原型添加方法与属性(给prototype指向的对象添加方法与属性,原型可以看成prototype指定的对象)
//原型是一个对象
//方法1
Gadget.prototype.price = 100;
100
Gadget.prototype.rating = 3;
3
Gadget.prototype.getInfo = function(){
return 'Rating: '+this.rating+', price: '+this.price;
};
//方法2,如果不想将它们逐一添加到原型对象中去,可以用一个对象覆盖
Gadget.prototype = {
price: 100,
ration: 3
}
使用原型的方法与属性
原型是给它实例的对象提供支持的。使用原型先要实例对象,在由实例的对象调用。
var newtoy = new Gadget('webcam','black');
undefined
newtoy.whatAreYou();
"I am a black webcam"
newtoy.getInfo();
"Rating: undefined, price: 100"
可看newtoy不但能调用Gadget本身的this方法,还能调用Gadget的prototype内的方法。说明prototype(对象属性)的所有属性和方法,都会被构造函数的实例继承。两者最大的区别是实时性。
Gadget.gad = 'gadget';
"gadget"
newtoy.gad; //构造函数添加了 gad 属性,以前创建的对象无变化
undefined
Gadget.prototype.pro = 'prototype'; //原型中添加了新属性,以前创建的对象也可以访问。
"prototype"
newtoy.pro;
"prototype"
原型具有实时性,当原型修改后甚至会影响在修改之前就已经创建了的对象。
利用自身属性重写原型属性
当对象查找一个属性时,先是在自身属性中查找,如果没有找到在去原型链(prototype)查找。也就是说自身属性的优先级高于原型属性(当自身与原型有相同属性时,访问的是自身属性)
function Gadget(name){
this.name = name;
}
undefined
Gadget.prototype.name = 'mirror';
"mirror"
var toy = new Gadget('camera');
undefined
toy.name; //访问的是自身的name属性
"camera"
constructor始终指向创建当前对象实例的(构造)函数,如 toy.constructor === Gadget。说明toy是由Gadget构造的。
X.hasOwnProperty('Y') 用来判断X对象是否有Y属性,当前对象不包括原型。
Gadget.hasOwnProperty('name');
true
toy.constructor.hasOwnProperty('name'); //这两个是等价的,因为toy.constructor就是Gadget
true
X.propertyIsEnumerable('Y')用来判断X对象的Y属性是否可以被枚举。
是X对象的内容,不包括原型。对于所有的原型属性都会返回false。同时数组的length属性和constructor也是返回false。
toy.constructor.prototype.propertyIsEnumerable('color');
true
//toy.constructor === Gadget 而 Gadget.prototype 也是在一个对象,而这个对象有color属性,返回true
使用fin in遍历时,会把原型的属性也遍历出来:
Gadget.prototype.color = 'red';
"red"
var toy = new Gadget();
undefined
for(var i in toy)
console.log(i+':'+toy[i]);
age:12 debugger eval code:2:11
color:red //可见这个属性是原型里的
isPrototypeOf() 这个方法会告诉我们当前对象是否是另一个对象的原型
var monkey = {
hair: true,
feeds:'bananas',
breathes:'air'
};
undefined
function Human(name){
this.name = name;
}
undefined
Human.prototype = monkey;
Object { hair: true, feeds: "bananas", breathes: "air" }
var george = new Human('George');
undefined
monkey.isPrototypeOf(george); //monkey是不是george的原型
true
Object.getPrototypeOf(x) 获取x的原型
Object.getPrototypeOf(george) === monkey;
true
神秘的__proto__链接
它会指向原型。指向的是一个对象。__proto__是某个实例对象的属性,而prototype则是属于构造器函数的属性。
function a1(){}
undefined
a1.prototype.a2 = 12;
12
var a3 = new a1();
Object { }
a3.constructor.prototype === a1.prototype;
true
a3.__proto__ == a1.prototype;
true
扩展内建对象
给数组添加一个inArray函数,可以用来查看这个数组有没有特定的值。
Array.prototype.inArray = function (needle){
for(var i = 0; i < this.length; i++){ //this指的就是当前数组
if(this[i] === needle){
return true;
}
}
return false;
}
function inArray()
var a = [1,2,3,4,5];
Array(5) [ 1, 2, 3, 4, 5 ]
a.inArray(3);
true
a.inArray(10);
false
给String添加一个 reverse()方法。用于反转字符串。
String.prototype.reverse = function(){
return Array.prototype.reverse.apply(this.split('')).join('');
}
function reverse()
'asdf'.reverse();
"fdsa"
在扩展内建对象的时候,首先应该先检查该方法是否已经存在。当方法存在的时候就就忘用原生方法。
if(typeof Array.prototype.reverse !== 'function'){
console.log('对象不存在');
}
原型陷阱
function Dog(){}
undefined
Dog.prototype = {};
Object { }
new Dog().constructor === Dog;
false
当我们重写某对象的prototype时,constructor属性会出错。
Dog.prototype.constructor = Dog //每次重写对象的prototype,都要手动修改constructor属性
function Dog()
new Dog().constructor.prototype === Dog.prototype;
true
上一篇: 微信公众平台PHP开发