searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享

Javascript深入理解之继承与原型链

2023-05-23 01:45:16
13
0
Javascript深入理解之继承与原型链
 
1.构造函数、原型、实例的关系
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针[[Prototype]]
function Foo() {
	this.a = 123;
}

Foo.prototype.b = 456;

let AA = new Foo();

console.dir(Foo.prototype);
console.dir(Foo.prototype.constructor);
console.dir(AA.__proto__);

// Foo为构造函数
// AA为实例
// Foo.prototype为原型对象
// Foo.prototype的constructor指向构造函数
// AA的__proto__指向原型对象
 
 
2.原型链
 
关于原型链的定义,我们来看一下MDN里面的定义“在 javaScript 中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype chain)。”  
 
3.原型链实例与继承
function Foo() {
	this.nameOne = 123;
	this.toOne = function() {
		return this.nameOne;
	}
}

function FooTwo() {
	this.nameTwo = 456;
	this.toTwo = function() {
		return this.nameTwo;
	}
}


FooTwo.prototype = new Foo();

/* 当我们对对象的prototype属性进行替换时,可能会对对象constructor属性产生一定的副作用,因此,在对prototype进行替换后,要对对象的constructor进行重置,避免陷入原型陷进。*/ 
FooTwo.prototype.constructor = FooTwo;

let aa = new FooThree();
console.log(aa.nameOne);	// => 123
console.log(aa.nameTwo);	// => 456
console.log(aa.toOne());	// => 132
console.log(aa.toTwo());	// => 456	
 
关于原型陷阱请看[JavaScript深入理解之原型](http://blog.csdn.net/zza000000/article/details/54142510) 
 
上例中:定义了两个类型:Foo和FooTwo,每个类型分别有一个属性和方法,且FooTwo继承了Foo,继承是通过创建Foo的实例,并将该实例赋给Foo.prototype实现的。实现的本质是重写原型对象,代之以一个新类型的实例,即原来存在于Foo的实例中的方法现在也存在于FooTwo.prototype中了,这样就继承了Foo的属性和方式,实现了继承。通俗一点说,A构造函数要继承B构造函数的属相和方法,则将B的实例赋值给A的prototype属性。
 
看下面一个例子
 
function Foo() {
	this.name = 123;
	this.toString = function() {
		return this.name;
	}
}

function FooTwo() {
	this.nameTwo = 456;
}

function FooThree() {
	this.name = 789;
	this.toStr = function() {
		return this.name;
	}
}

FooTwo.prototype = new Foo();
FooThree.prototype = new FooTwo();

FooTwo.prototype.constructor = FooTwo;
FooThree.prototype.constructor = FooThree;

let aa = new FooThree();
console.log(aa.nameTwo);		// => 456
console.log(aa.toString());		// => 789
console.log(aa.toStr());		// => 789

// aa同时是三个构造器的实例
console.log(aa instanceof Foo);			// => true
console.log(aa instanceof FooTwo);		// => true
console.log(aa instanceof FooThree);	// => true
 
上例中:两个输出都打印789,因为在继承中,继承的方法和属性, 而且是单纯的方法和属性,FooThree实际上是下面这样:
function FooThree() {
	this.nameTwo = 456;
	this.name = 789;			// 因为我们设置constructor指向FooThree
	this.toStr = function() {
		return this.name;
	}
}
 
4.构造函数模式继承
function Foo(name) {
	this.name = name;
	this.say() = function() {
		return this.name;
	}
}

function FooTwo() {
	// 继承Foo,同时还传递参数
	Foo.call(this, 123);
}

let aa = new FooTwo();

console.log(aa.name); 	// => 123
console.log(aa.say());	//TypeError: say is not a function
构造函数模式缺点在于只能继承属性,不能继承方法 
 
5.组合继承
function Foo(name) {
	this.name = name;
}

Foo.prototype.say = function() {
	return this.name
}

function FooTwo(name, age) {
	// 继承属性
	Foo.call(this, name);
	this.age = age;
}

// 继承方法
FooTwo.prototype = new Foo();
FooTwo.prototype.constructor = FooTwo;
FooTwo.prototype.say = function() {
	return this.name;
}

let aa = new FooTwo('aa', 26);

console.log(aa.name);		// => aa
console.log(aa.age);		// => 26
console.log(aa.say());		// => aa
 
 
5.其它继承方式还有:原型式继承、寄生式继承等
0条评论
作者已关闭评论
c****n
2文章数
0粉丝数
c****n
2 文章 | 0 粉丝
c****n
2文章数
0粉丝数
c****n
2 文章 | 0 粉丝

Javascript深入理解之继承与原型链

2023-05-23 01:45:16
13
0
Javascript深入理解之继承与原型链
 
1.构造函数、原型、实例的关系
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针[[Prototype]]
function Foo() {
	this.a = 123;
}

Foo.prototype.b = 456;

let AA = new Foo();

console.dir(Foo.prototype);
console.dir(Foo.prototype.constructor);
console.dir(AA.__proto__);

// Foo为构造函数
// AA为实例
// Foo.prototype为原型对象
// Foo.prototype的constructor指向构造函数
// AA的__proto__指向原型对象
 
 
2.原型链
 
关于原型链的定义,我们来看一下MDN里面的定义“在 javaScript 中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototype chain)。”  
 
3.原型链实例与继承
function Foo() {
	this.nameOne = 123;
	this.toOne = function() {
		return this.nameOne;
	}
}

function FooTwo() {
	this.nameTwo = 456;
	this.toTwo = function() {
		return this.nameTwo;
	}
}


FooTwo.prototype = new Foo();

/* 当我们对对象的prototype属性进行替换时,可能会对对象constructor属性产生一定的副作用,因此,在对prototype进行替换后,要对对象的constructor进行重置,避免陷入原型陷进。*/ 
FooTwo.prototype.constructor = FooTwo;

let aa = new FooThree();
console.log(aa.nameOne);	// => 123
console.log(aa.nameTwo);	// => 456
console.log(aa.toOne());	// => 132
console.log(aa.toTwo());	// => 456	
 
关于原型陷阱请看[JavaScript深入理解之原型](http://blog.csdn.net/zza000000/article/details/54142510) 
 
上例中:定义了两个类型:Foo和FooTwo,每个类型分别有一个属性和方法,且FooTwo继承了Foo,继承是通过创建Foo的实例,并将该实例赋给Foo.prototype实现的。实现的本质是重写原型对象,代之以一个新类型的实例,即原来存在于Foo的实例中的方法现在也存在于FooTwo.prototype中了,这样就继承了Foo的属性和方式,实现了继承。通俗一点说,A构造函数要继承B构造函数的属相和方法,则将B的实例赋值给A的prototype属性。
 
看下面一个例子
 
function Foo() {
	this.name = 123;
	this.toString = function() {
		return this.name;
	}
}

function FooTwo() {
	this.nameTwo = 456;
}

function FooThree() {
	this.name = 789;
	this.toStr = function() {
		return this.name;
	}
}

FooTwo.prototype = new Foo();
FooThree.prototype = new FooTwo();

FooTwo.prototype.constructor = FooTwo;
FooThree.prototype.constructor = FooThree;

let aa = new FooThree();
console.log(aa.nameTwo);		// => 456
console.log(aa.toString());		// => 789
console.log(aa.toStr());		// => 789

// aa同时是三个构造器的实例
console.log(aa instanceof Foo);			// => true
console.log(aa instanceof FooTwo);		// => true
console.log(aa instanceof FooThree);	// => true
 
上例中:两个输出都打印789,因为在继承中,继承的方法和属性, 而且是单纯的方法和属性,FooThree实际上是下面这样:
function FooThree() {
	this.nameTwo = 456;
	this.name = 789;			// 因为我们设置constructor指向FooThree
	this.toStr = function() {
		return this.name;
	}
}
 
4.构造函数模式继承
function Foo(name) {
	this.name = name;
	this.say() = function() {
		return this.name;
	}
}

function FooTwo() {
	// 继承Foo,同时还传递参数
	Foo.call(this, 123);
}

let aa = new FooTwo();

console.log(aa.name); 	// => 123
console.log(aa.say());	//TypeError: say is not a function
构造函数模式缺点在于只能继承属性,不能继承方法 
 
5.组合继承
function Foo(name) {
	this.name = name;
}

Foo.prototype.say = function() {
	return this.name
}

function FooTwo(name, age) {
	// 继承属性
	Foo.call(this, name);
	this.age = age;
}

// 继承方法
FooTwo.prototype = new Foo();
FooTwo.prototype.constructor = FooTwo;
FooTwo.prototype.say = function() {
	return this.name;
}

let aa = new FooTwo('aa', 26);

console.log(aa.name);		// => aa
console.log(aa.age);		// => 26
console.log(aa.say());		// => aa
 
 
5.其它继承方式还有:原型式继承、寄生式继承等
文章来自个人专栏
文章 | 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0