javascript是面向对象风格,基于原型的语言。
目标:了解js面向对象和原型原型链的关系
面向对象(OOP)的特点?
封装、继承、多态
1.封装:是将数据和代码捆绑到一起,对象的某些数据和代码可以是私有的,不能被外界访问,以此实现对数据和代码不同级别的访问权限。防止了程序相互依赖性而带来的变动影响,面向对象的封装比传统语言的封装更为清晰、更为有力。有效实现了两个目标:对数据和行为的包装和信息隐藏。
2.继承:简单地说就是一种层次模型,这种层次模型能够被重用。层次结构的上层具有通用性,但是下层结构则具有特殊性。在继承的过程中类则可以从最顶层的部分继承一些方法和变量。类除了可以继承以外同时还能够进行修改或者添加。通过这样的方式能够有效提高工作效率。在这里举一个例子,当类X继承了类Y后,此时的类X则是一个派生类,而类Y属于一个基类。 继承是从一般演绎到特殊的过程,可以减少知识表示的冗余内容,知识库的维护和修正都非常方便。更有利于衍生复杂的系统。
3.多态:多种形态,指不同事物具有不同表现形式的能力。多态机制使具有不同内部结构的对象可以共享相同的外部接口,通过这种方式减少代码的复杂度。一个接口,多种方式。比如:相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息通过某一种标识可以产生不同的结果,这种现象称为多态性。
在javascript中OOP的呈现。
1.封装
基于构造函数的封装:
function schoolmate(name,age,grade){
this.name = name;
this.age = age;
this.grade = grade;
}
let g1=new schoolmate('赵云','11','88');
let g2=new schoolmate('韩信','12','100');
console.log(g1,g2)
/*ps:当然还有其他方式不一一列举*/
2.继承
想要了解js中的继承我们先看看什么是javascript的原型和原型链:[1]。
基于原型的继承:
// 父类方法(Superclass)
function Superclass() {
this.supName = "我是父类"
}
// 父类添加原型方法
Superclass.prototype.showSupName = function () {
console.log(this.supName)
}
//子类(Subclass)
function Subclass() {
this.subName = "我是子类"
}
/**
* 1 让子类能访问父类的方法
* 2 让子类的constructor属性指向自身(constructor属性是对函数本身的引用)
**/
Subclass.prototype = new Superclass();
Subclass.prototype.constructor = Subclass
// 子类添加原型方法
Subclass.prototype.showSubName = function () {
console.log(this.subName)
}
// 子类调用父类方法
var sub = new Subclass();
sub.showSupName();
/*ps:如果想要继承父类的属性可调用父类的function.call(thisArg, arg1, arg2, ...);方法给父类提供子类的this值来实现*/
3.多态
一个接口,多种方式。
function getName(person) {
person.name();
}
var tang = function () { }
tang.prototype.name = function () {
console.log("我是唐三")
}
var wu = function () { }
wu.prototype.name = function () {
console.log("我是小舞")
}
var rong = function () { }
rong.prototype.name = function () {
console.log("我是荣荣")
}
getName(new tang())
getName(new wu())
/*ps:多态是面向对象的特点,目的是为了让程序更方便,不必太局限于此示例*/
javascript中的原型?
在javascript中,函数可以有属性。 每个函数都有一个特殊的属性叫作原型(prototype)。
//例:
function User(name) {
this.name = name
}
console.log(User.prototype)
//上面定义了一个User函数,运行后我们得到了其原型对象。
{
constructor:ƒ User(name, pass) ,
__proto__: {
constructor: ƒ Object(),
hasOwnProperty: ƒ hasOwnProperty(),
isPrototypeOf: ƒ isPrototypeOf(),
propertyIsEnumerable: ƒ propertyIsEnumerable(),
toLocaleString: ƒ toLocaleString(),
toString: ƒ toString(),
valueOf: ƒ valueOf()
}
}
我们在User的原型上添加输出名字的方法
function User(name) {
this.name = name
}
User.prototype.getUsername =function(){
console.log(this.name);
}
console.log(User.prototype)
//现在看看User函数的原型变化。
{
constructor:ƒ User(name, pass),
getUsername:ƒ (),
__proto__: {
constructor: ƒ Object(),
hasOwnProperty: ƒ hasOwnProperty(),
isPrototypeOf: ƒ isPrototypeOf(),
propertyIsEnumerable: ƒ propertyIsEnumerable(),
toLocaleString: ƒ toLocaleString(),
toString: ƒ toString(),
valueOf: ƒ valueOf()
}
}
然后,我们可以使用 new 运算符来在现在的这个原型基础之上,创建一个 User 的实例,得到一个实例对象。
function User(name) {
this.name = name
}
User.prototype.getUsername =function(){
console.log(this.name);
}
var onUser=new User()
console.log(onUser);
//现在看看onUser的实例对象。
{
name:'张三',
__proto__: {
constructor:ƒ User(name, pass),
getUsername:ƒ (),
__proto__: {
constructor: ƒ Object(),
hasOwnProperty: ƒ hasOwnProperty(),
isPrototypeOf: ƒ isPrototypeOf(),
propertyIsEnumerable: ƒ propertyIsEnumerable(),
toLocaleString: ƒ toLocaleString(),
toString: ƒ toString(),
valueOf: ƒ valueOf()
}
}
}
仔细对比会发现onUser实例对象会有一个(proto )私有属性,并且指向User构造函数的原型。
function User(name) {
this.name = name
}
User.prototype.getUsername =function(){
console.log(this.name)
}
var onuser=new User('张三')
console.log(onUser.__proto__===User.prototype)
//true
什么是原型链?
上面我们说到,函数的prototype属性即为原型,并且可以在原型上添加属性或者方法。仔细查看prototype会发现,每个构造函数的原型对象(prototype)上也会有一个自己的隐式原型对象 ( proto ) ,proto 上还有proto 直到原型对象为null,这种关系称为原型链。
希望对学习的小伙伴有帮助。谢点赞~~转请注明链接
-
向上滚动鼠标至段落头
网友评论