方法或属性之间的区别
//对象构造函数
function People(name) {
//私有属性,只能在对象构造函数内部访问
var NATION = 'china';
//共有属性,对象实例化后可以调用
this.name = name;
//对象方法
this.introduce = function () {
console.log(this.name);
console.log(this.age); //使用原型方法扩充的属性可以在类内部使用
console.log(this.sayName());//使用原型方法扩充的方法可以在类内部使用
console.log(People.foot);//静态属性调用时格式为[对象.静态属性]
}
}
//类方法(共有静态方法),只能通过类名称直接调用
People.talk = function () {
console.log('People can talk ')
}
//类属性 (公有静态属性),不能使用 【this.属性】,通过类名直接访问
People.foot = 2
//原型属性 (公有共享属性),当作是类内部的属性使用【this.原型属性】,也可以当成公有静态属性使用【对象.prototype.原型属性】
People.prototype.age = 20;
//原型方法 (公有共享方法)
People.prototype.sayName = function () {
//如果原型方法当作静态方法直接调用时,this.name无法被调用
console.log("My name is " + this.name);
}
People.talk(); //类方法也是静态方法,类方法不需要通过实例化对象去调用,可以直接使用 【对象.静态方法()】
console.log(People.foot) //类属性的调用:类名称.方法名称 = function([参数...]){ 语句行; }
People.prototype.sayName(); //原型方法当成静态方法使用时【对象.prototype.方法()】
console.log(People.prototype.age);//原型属性当作静态属性使用时【对象.prototype.原型属性】
var tom = new People('tom');//对象方法和原型方法需要实例化对象后才可以使用
tom.sayName(); //对象方法必须实例化对象
tom.introduce(); //原型方法必须实例化对象
console.log(tom.age);//错误,公有静态属性只能使用 【对象.属性】调用
- 对象方法包括构造函数中的方法以及构造函数原型上面的方法;
- 类方法,其实这里的类就是一个函数,在js中由于函数也是一个对象,所以可以为函数添加属性以及方法,这种方法在node中用的比较多;
在原型上定义方法
原型对象的用途是为每个实例对象存储共享的方法和属性,它仅仅是一个普通对象而已。并且所有的实例是共享同一个原型对象,因此有别于实例方法或属性,原型对象仅有一份。所以下面的等式都是成立的:
console.log(tom.sayName == new People().sayName)//true
console.log(new People('a').sayName == new People('b').sayName) //true
- 将方法定义为原型方法,原型方法避免了每次调用构造函数时对属性或方法的构造,创建对象快。
- 在原型上面添加该方法,就能实现共享。这样就不用每一次初始化一个实例的时候,为其分配相应的内存了,节省空间。
实例和原型的访问顺序
如果实例上的方法或属性与原型上的方法或属性重名了,会访问谁呢?
function Person(){
this.name = 'a';
this.sayName = function(){
console.log('a')
}
}
Person.prototype.name = 'b';
Person.prototype.sayName = function(){
console.log('b')
}
var person = new Person();
console.log(person.name) //'a'
person.sayName() //'a'
在js中,对象在调用一个方法或属性时会首先在自身里寻找是否有该方法或属性,若没有,则去原型链上去寻找,依次层层递进,这里的原型链就是实例对象的proto属性。