javascript对象方法、类方法、原型方法

  • 对象方法
  • 类方法
  • 原型方法

1.分类定义

代码

function Student(theName){
    this.name = theName || 'A student';
    // 对象方法
    this.reading = function(){
        console.log(this.name + ' can read!')
    }
}

// 类方法
Student.learning = function(){
    console.log('The student can learn!')
}

// 原型方法
Student.prototype.writing = function(){
    console.log('The students can write!')
}

测试

var tom = new Student('Tom');
tom.reading();//Tom can read
Student.writing();//The student can write
tom.learning();//The students can learn

这里用三种方法,分别定义了一个学生应有的技能。学生都会学习,而学生Tom可以读书、写字。

2.prototype

javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用

在看prototype之前,先了解几个例子

2.1私有属性、方法

function Student(){
    var age = 23;//私有属性
    var canGames = function(){
        //私有方法
    }
}

a.此时外部无法访问agecanGames——所以就不知道该学生的年龄,也不知道他会玩游戏。
b.只能在函数内部访问agecanGames——只有学生自己知道自己的年龄,自己会玩游戏

测试

var tom = new Student();
tom.age;//undefined
tom.canGames;//tom.canGames is not a function

2.2静态属性、方法

代码

function Student(){
}

Student.type = 'junior school student';
// 上面说到的类方法
Student.canWalk = function(){
    console.log('Student can walk!')
}

测试

Student.type;//junior school student
Student.canWalk();//Student can walk!

var tom = new Student();
tom.type;//undefined;
tom.canWalk();//tom.canWalk is not a function

注意:

这种类属性叫做静态属性,类方法叫做静态方法
只能通过类属性访问,不能通过实例访问

2.3实例变量、方法

代码

function Student(){
    // 上面说的对象方法
    this.scores = [];
    this.reading = function(){

    }
}

测试

var tom = new Student();
tom.scores.push(90);
tom.reading = {};
console.log(tom.scores);//[90]
console.log(typeof tom.reading);//object

var jack = new Student();
console.log(jack.scores);//[]
console.log(typeof jack.reading);//function

可以看出,上面两个实例之间互不影响。因为数组和函数都是引用类型,所以虽然名称相同,但却已经分配了不同地址。也就是说,tom和jack的属性都是对Student的一个复制。

故而:

当一两个实例没有任何影响,当需要构建成千上万个实例的时候,每个实例都会分配新的地址,都会拷贝一份。内存占用可想而知…

这时,就需要 prototype

3.3prototype

function Student(){
}
Student.prototype;

观察
这里写图片描述

这里并没有报错,并且控制打出一系列信息。


说明:

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,默认情况下prototype属性会默认获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针。

function Student(name){
    this.name = name;
}
Student.prototype.introduce = function(){
    console.log(this.name);
}

var tom = new Student('Tom');
var jack = new Student('Jack');

这里写图片描述

可以看出,在新建一个Student的实例时,出现了__proto__这个属性,而这个属性正好指向了Studentprototype属性
当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(很多浏览器这个指针名字为__proto__)指向构造函数的prototype


那么prototype原型方法是否会像函数方法一样,每个实例都单独复制一遍属性呢?

再测试一下,代码

function Student(name){

    this.name = name

}

Student.prototype.learned = [];

Student.prototype.readed = function(){
    console.log(1);
};

测试

var tom = new Student('Tom');
tom.learned.push('Java');
tom.readed = {};
console.log(tom.learned);//['Java']
console.log(typeof tom.readed);//object

var jack = new Student('Jack');
console.log(jack.learned);//['Java']
console.log(typeof jack.readed);//function

这里写图片描述

方才说了实例中的__proto__指向的是Student中的prototype(图中红色圈中)。所以在实例jack的时候learned被tom改变了,jack的learned也改变了,因为指向的是同一个prototype的learned属性。

可是为什么,tom也改变了function,jack中的没有变?

因为javascript中,属性的查找:先去查找当前对象属性,是否有相应同名属性或方法;如果没有,再去prototype中查找;如果prototype也没有;继续向prototype的constructor中的prototype递归查找;如果一直递归到Object对象还没有,则停止查找。


上面tom定义了一个同名属性readed(图中黑色圈中),所以直接匹配成功,未去查询prototype中的readed。

总结

  • 需要复用的组件,放入原型方法中定义 Class.prototype.XXX
  • 需要互不影响、分开工作的组件,放入对象方法中定义this.XXX
  • 禁止实例调用,通过类属性调用,放入类方法中定义Class.XXX

贴个简单例子:

function Student(name,age){
    this.name = name;
    this.age = age;
}

Student.prototype.introduce = function(){
    console.log('I\'m ' + this.name + ', and I am a junior school student!')
}

Student.makeFriends = function(){
    var tom = new Student('Tom',12);
    var jack = new Student('Jack',13);
    tom.introduce();
    jack.introduce();
}

测试:

Student.makeFriends();

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值