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对象,他只能继承调用者内部的实例对象。

  

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

目录
相关文章
|
4月前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
1月前
|
设计模式 JavaScript 算法
浅谈几种js设计模式
设计模式是软件开发中的宝贵工具,能够提高代码的可维护性和扩展性。通过单例模式、工厂模式、观察者模式和策略模式,我们可以解决不同场景下的实际问题,编写更加优雅和高效的代码。
33 8
|
2月前
|
设计模式 数据安全/隐私保护
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
这篇文章介绍了在Next.js框架下,如何处理中后台管理系统中特殊页面(如登录页)不包裹根布局(RootLayout)的问题。作者指出Next.js的设计理念是通过布局的嵌套来创建复杂的页面结构,这虽然保持了代码的整洁和可维护性,但对于特殊页面来说,却造成了不必要的布局包裹。文章提出了一个解决方案,即通过判断页面的skipGlobalLayout属性来决定是否包含RootLayout,从而实现特殊页面不包裹根布局的目标。
127 33
|
4月前
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
70 2
|
4月前
|
JavaScript 前端开发
Javascript如何实现继承?
【10月更文挑战第24天】JavaScript 中实现继承的方式有很多种,每种方式都有其优缺点和适用场景。在实际开发中,我们需要根据具体的需求和情况选择合适的继承方式,以实现代码的复用和扩展。
|
4月前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
4月前
|
JavaScript 前端开发 开发者
js实现继承怎么实现
【10月更文挑战第26天】每种方式都有其优缺点和适用场景,开发者可以根据具体的需求和项目情况选择合适的继承方式来实现代码的复用和扩展。
51 1
|
6月前
|
自然语言处理 JavaScript 前端开发
一文梳理JavaScript中常见的七大继承方案
该文章系统地概述了JavaScript中七种常见的继承模式,包括原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合继承等,并探讨了每种模式的实现方式及其优缺点。
一文梳理JavaScript中常见的七大继承方案
|
5月前
|
设计模式 JavaScript 前端开发
JavaScript设计模式--访问者模式
【10月更文挑战第1天】
57 3
|
6月前
|
JavaScript 前端开发
js之class继承|27
js之class继承|27

热门文章

最新文章