JavaScript prototype(原型对象)学习总结1

分类:计算机 | 前端 | JavaScript | 综合 1065
更新:2021-08-24 00:21:07
编辑

JavaScript也是面向对象的语言,但它是一种基于原型prototype的语言,而不是基于类的语言。在JavaScript中,类和对象看起来没有太多的区别。

所有的JavaScript对象都会从一个prototype(原型对象)中继承属性和方法。

1 什么是prototype

function定义的对象有一个prototype属性,prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别。在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身。是不是很绕?用伪代码表示如下:

var function{
 prototype:prototype{
  constructor:constructor==function
 }
}

还不明白?看图吧:

2 prototype的作用

这个prototype到底有什么作用呢?看下面的例子:

function uw3c(){
}

uw3c.prototype.name='a';
var test=new jb51();
alert(test.name); //"a"

奇怪吧,明明没有为test设置name属性,可是为什么会有值?

这就是prototype的功劳了,uw3c中prototype属性中的name对象,在uw3c被new构造函数之后,被继承到了对象test的属性中。接着看:

var name="js";
function uw3c(name){
 alert(this.name); //"css"
}
uw3c.prototype.name="css";
var test=new uw3c();
test();

为什么alert的值不是“js”?这个过程大致如下:

var test={};
uw3c.call(test);

第一步是建立一个新对象(test)。

第二步将该对象(test)内置的原型对象设置为构造函数(就是uw3c)prototype属性引用的那个原型对象。

第三步就是将该对象(test)作为this参数调用构造函数(就是uw3c),完成成员设置等初始化工作。

其中第二步中出现了 一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就指向了函数uw3c的Prototype对象。在uw3c的prototype对象中出现的任何属性或者函数都可以在test对象中直接使用,这个就是JS中的原型继承了。

通常,这样创建一个对象:

function person(name){
 this.sayHi=function(){
 alert('hi '+this.name);
 }

 this.name=name;
}

var p=new person("dan");
p.sayHi();

以上,使用new关键字,通过对象(函数也是特殊对象)创建一个对象实例。

在基于类的语言中,属性或字段通常都是在类中事先定义好了,但在JavaScript中,在创建对象之后还可以为类添加字段。

function animal(){}

var cat=new animal();
cat.color="green";

以上,color这个字段只属于当前的cat实例。

对于后加的字段,如果想让animal的所有实例都拥有呢?

-- 使用prototype
function animal(){}

animal.prototype.color="green";
var cat=new animal();
var dog=new animal();
console.log(cat.color); //green
console.log(dog.color); //green

通过prototype不仅可以添加字段,还可以添加方法。

function animal(){}
animal.prototype.color="green";
var cat=new animal();
var dog=new animal();
console.log(cat.color); //green
console.log(dog.color); //green
animal.prototype.run=function(){
console.log("run");
}
dog.run();

原来通过prototype属性,在创建对象之后还可以改变对象的行为。

比如,可以为数组这个特殊对象添加一个方法。

Array.prototype.remove=function(elem){
var index=this.indexof(elem);
if(index>=0){
 this.splice(index,1);
}
}
var arr=[1,2,3];
arr.remove(2);

除了通过prototype为对象定义属性或方法,还可以通过对象的构造函数来定义类的属性或方法。

function animal(){
this.color="green";
this.run=function(){
console.log("run");
}
}

var mouse=new animal();
mouse.run();

以上做法也可以让所有的animal实例共享所有的字段和方法。并且还有一个好处是可以在构造函数中使用类的局部变量。

function animal(){
var runAlready = false;
this.color = "green";
this.run = funciton(){
if(!runAlreadh){
console.log("start running");
} else {
console.log("already running")
}
}
}

其实,一个更加实际的做法是通过构造函数结合prototype定义一个类的字段和行为。

function animal(){
var runAlready = false;
this.run = function(){
if(!runAlready){
console.log('i am running');
} else {
console.log("i am already running");
}
}
}
animal.prototype.color = '';
animal.prototype.hide = funciton(){
console.log("");
}
var horse = new animal();
horse.run();
horse.hide();

Prototype允许我们在创建对象之后来改变对象或类的行为,并且这些通过prototype属性添加的字段或方法所有对象实例是共享的。

转载地址

https://www.jb51.net/article/79549.htm