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

来源:互联网 发布:斗鱼直播伴侣mac版 编辑:程序博客网 时间:2024/05/04 12:06
  • 对象方法
  • 类方法
  • 原型方法

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 readStudent.writing();//The student can writetom.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;//undefinedtom.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 studentStudent.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);//objectvar 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);//objectvar 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();

这里写图片描述

0 0
原创粉丝点击