javascript设计模式--继承(上)-阿里云开发者社区

开发者社区> bill.kang> 正文

javascript设计模式--继承(上)

简介:   本章的主题是继承,分为上下两部分来介绍,上主要来介绍call和apply方法,下用来介绍继承的几种实现方式。   在介绍继承的时候,call和apply是一个绕不过去的话题,也是大家需要深入了解的知识。
+关注继续查看

  本章的主题是继承,分为上下两部分来介绍,上主要来介绍call和apply方法,下用来介绍继承的几种实现方式。

  在介绍继承的时候,call和apply是一个绕不过去的话题,也是大家需要深入了解的知识。下面我们来看看call的定义(apply和call基本是一样的,只是参数不同,这里不做介绍了):

call 方法
请参阅
应用于:Function 对象
要求
版本 5.5
调用一个对象的一个方法,以另一个对象替换当前对象。

call([thisObj[,arg1[, arg2[,   [,.argN]]]]])
参数
thisObj
可选项。将被用作当前对象的对象。
arg1, arg2, , argN
可选项。将被传递方法参数序列。
说明
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

  定义总是让人看不懂,还是直接上例子直接。

例1:

function Person(name) {
  this.name = name;
  this.getName = function () {
    return this.name;
  }
}

function Man(name, age) {
  Person.call(this, arguments[0]);
  this.age = age;
  this.setAge = function (age) {
    this.age = age;
  }
}

var man = new Man('jason', 'man');
alert(man.getName()); //jason 

以Person.call(this,argument[0])为例:

call方法的调用者:一个对象的方法(在js里面方法/函数也是对象),调用者为Person
call方法的参数:一个新对象(man),这个对象的作用是“拦截”对象Person,来运行本来属于Person的getName方法;而 argument[0]就是给method传递参数了
call方法的结果:Person.call(man,argument[0])类似于:man=new Person(argument[0])
call方法的作用:Person方法得到重用、共享,有new的特效,实现继承。

  那么通过call到底能继承什么内容呢?我通过下面的例子做以介绍。

  上面的例子是在构造函数里面调用了call,那么在构造函数外,代码运行的过程中能否实现继承呢?

例子2:

function Person(name) {
  this.name = name;
  this.getName = function () {
    return this.name;
  }
}

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

var man = new Man('jason', '25');
Person.call(man, 'jason');

alert(man.getName());//jason

  通过测试,man继承了Person的getName函数。前两次都是用Person去调用call方法,这次我们换成person,看看效果如何。

例3:

function Person(name) {
  this.name = name;
  this.getName = function () {
    return this.name;
  }
}

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

var person = new Person('person');
var man = new Man('jason', '25');

person.call(man, 'jason');
alert(man.getName()); //person.call is not a function

  结果报错,原因是其实很简单,call的调用者只能是Function 对象,person是Function的实例,Person才是Function对象。

  那么这次我们用person.getName来调用call,看会是什么样的结果。

例4:

function Person(name) {
  this.name = name;
  this.getName = function () {
    return this.name;
  }
}

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

var person = new Person('person');
var man = new Man('jason', '25');

person.getName.call(man, 'jason');
alert(man.getName()); //man.getName is not a function

  在这里肯定会有人疑问了,不是只要做为方法就能调用call吗,那man就应该继承getName啊。前半句话是对的,但是后半句就不一定了。那通过call到底继承了哪些内容呢?

例5:

function Person(name) {
  this.name = name;
  this.getName = function () {
    this.address = 'address';  //代码稍加改动,在getName方法中增加了一个变量    
    return
this.name;   } } function Man(name, age) {   this.age = age;   this.setAge = function (age) {     this.age = age;   } } var person = new Person('person'); var man = new Man('jason', '25'); person.getName.call(man, 'jason'); //在这里我们遍历man,看他到底包含了哪些对象
for (pro in man) {   alert(pro + ":" + man[pro]); }
//输入结果:
//age:25
//setAge:function (age) {
//    this.age = age;
//}
//address:address

  结果很特别吧,居然多了一个address。结果也就很明显了,调用call,call的被调用者会继承调用者内部的实例对象,而不是调用者本身。

  下面我们在做最后一个测试,看call是否能继承对象的prototype里面的对象。

例6:

function Person(name) {
  this.name = name;
}

Person.prototype.getName = function () {
  return this.name;
}

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

var man = new Man('jason', '25');
Person.call(man, 'jason');

alert(man.getName()); //man.getName is not a function

  结果很显然,通过call不能继承调用者的prototype对象,他只能继承调用者内部的实例对象。

  

  今天的内容就到此了,希望对大家有帮助。

adpics.aspx?source=kbh1983&sourcesuninfo

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
10086 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
2962 0
javascript设计模式--封装和信息隐藏(下)
  今天讲解的内容是高级模式(Advanced Patterns),如何实现静态方法和属性,常量还有其他一些知识点。   1.静态方法和属性   其实要实现这一功能还是要借助于闭包。在上一讲中的第三种实现方式也使用了闭包,但通过那种实现,内部属性和方法是实例级别的。
731 0
《JavaScript设计模式》——1.8 方法还可以这样用
没错,但是你发现没,你调用了3个方法,但是你对对象a书写了3遍。这是可以避免的,那就要在你声明的每一个方法末尾处将当前对象返回,在JavaScript中this指向的就是当前对象,所以你可以将它返回。例如我们开始写的第一个对象还记得么?改动它很简单,像下面这样就可以。
1009 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
12076 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13891 0
《JavaScript设计模式》——2.2 包装明星——封装
闭包是有权访问另外一个函数作用域中变量的函数,即在一个函数内部创建另外一个函数。我们将这个闭包作为创建对象的构造函数,这样它既是闭包又是可实例对象的函数,即可访问到类函数作用域中的变量,如bookNum这个变量,此时这个变量叫静态私有变量,并且checkBook()可称之为静态私有方法。
1153 0
javascript设计模式--继承(下)
  本章的主题是继承,在javascript中要实现继承比其他面相对象语言要复杂的多,他主要使用原型实现继承。下面就介绍几种常用的实现继承的方式。   1.经典继承(Classical Inheritance)   我们首先创建一个Person类。
591 0
《JavaScript设计模式》——1.10 可以链式添加吗
本节书摘来自异步社区《JavaScript设计模式》一书中的第1章,第1.10节,作者:张容铭著,更多章节内容可以访问云栖社区“异步社区”公众号查看
963 0
《JavaScript设计模式》——第2章 写的都是看到的——面向对象编程 2.1两种编程风格——面向过程与面向对象
面向对象编程就是将你的需求抽象成一个对象,然后针对这个对象分析其特征(属性)与动作(方法)。这个对象我们称之为类。面向对象编程思想其中有一个特点就是封装,就是说把你需要的功能放在一个对象里。比如你大学毕业你来公司携带的行李物品没有一件一件拿过来,而是要将他们放在一个旅行箱里,这样不论携带还是管理都会更方便一些。
1270 0
+关注
bill.kang
从事软件研发十余年,入行前端开发六年有余,对前端工程化有一定认识。 现就职于客如云科技有限公司,任前端技术经理一职。
109
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载