我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Javascript基之js面向对象的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Javascript基之js面向对象的示例分析

这篇文章主要为大家展示了“Javascript基之js面向对象的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Javascript基之js面向对象的示例分析”这篇文章吧。

Javascript中的对象

什么是对象

我们可以把Javascript中对象理解为一组无序的键值对,就好像C#中的Dictionary<string,Object>一样。Key是属性的名称,而value可以为以下3种类型:

  1. 基本值(string, number, boolean, null, undefined)

  2. 对象

  3. 函数

var o = new Object();
o["name"] = "jesse"; //基本值作为对象属性
o["location"] = {   //对象作为对象属性
  "city": "Shanghai",
  "district":"minhang"
};

// 函数 作为对象属性
o["sayHello"] = function () {
  alert("Hello, I am "+ this.name + " from " + this.location.city);
}

o.sayHello();

遍历属性

  在C#中我们是可以用foreach对Dictionary<string,Object>进行遍历的,如果说对象在Javascript中是一组键值对的话,那我们如何进行遍历呢?

for (var p in o) {
  alert('name:'+ p + 
     ' type:' + typeof o[p]
    );
}
// name:name type:string
// name:location type:object
// name:sayHello type:function

上面的这种遍历方式会把原型中的属性也包括进来,关于什么是原型,以及如何区分原型和实例中的属性我们下面会讲到。

创建对象
  其实在上面我们已经创建了一个对象,并且使用了以下两种创建对象的方式。

  1. 利用new创建一个Object的实例。

  2. 字面量

我们上面的o是用第一种方式创建的,而o中的location属性则是用字面量的方式创建的。而第一种方式其实也有一种名字叫做构造函数模式,因为Object实际上是一个构造函数,为我们产生了一个Object的实例。如果对于构造函数这一块还有不清楚的话,赶紧去看我的第一篇 类型基础Object与object吧。

  除了以上两种方式以外,我们一些创建对象的方式,我们也来一起看一下:

工厂模式

function createPerson(name, age, job){
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;
  o.sayName = function(){
    alert(this.name);
  };
  return o;
}
var person1 = createPerson('Jesse', 29, 'Software Engineer');
var person2 = createPerson('Carol', 27, 'Designer');

这种模式创建的对象有一个问题,那就是它在函数的内部为我创建了一个Object的实例,这个实例跟我们的构造函数createPerson是没有任何关系的。

Javascript基之js面向对象的示例分析

因为我在内部用new Object()来创建了这个对象,所以它是Object的实例。所以如果我们想知道它是具体哪个function的实例,那就不可能了。

构造函数模式

  工厂模式没有解决对象识别的问题,但是我们可以想一下,Object()实际上也是一个函数,只不过当我在它前面加上一个new的时候,它就变成了一个构造函数为我们产生一个Object的实例。那么我同样也可以在其它函数前面加上new这样就可以产生这个函数的实例了,这就是所谓的构造函数模式。

function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function(){
    alert(this.name);
  };
}

var p1 = new Person('Jesse', 18, 'coder');
alert(p1 instanceof Person); // true

详解this
  this在Javascript中也可以算是一个很神奇对象,没错this是一个对象。我们在上一篇作用域和作用域链中讲到了变量对象,变量对象决定了在当前的执行环境中有哪些属性和函数是可以被访问到的,从某种程度上来说我们就可以把this看作是这个变量对象。我们之前提到了最大的执行环境是全局执行环境,而window就是全局执行环境中的变量对象,那么我们在全局环境中this===window是会返回true的。

Javascript基之js面向对象的示例分析

除了全局执行环境以外,我们还提到了另外一种执行环境,也就是函数。每一个函数都有一个this对象,但有时候他们所代表的值是不一样的,主要是这个函数的调用者来决定的。我们来看一下以下几种场景:

函数

function f1(){
 return this;
}

f1() === window; // global object

因为当前的函数在全局函数中运行,所以函数中的this对象指向了全局变量对象,也就是window。这种方式在严格模式下会返回undefined。

对象方法

var o = {
 prop: 37,
 f: function() {
  return this.prop;
 }
};

console.log(o.f()); // logs 37

在对象方法中,this对象指向了当前这个实例对象。注意: 不管这个函数在哪里什么时候或者怎么样定义,只要它是一个对象实例的方法,那么它的this都是指向这个对象实例的。

var o = { prop: 37 };
var prop = 15;

function independent() {
  return this.prop;
}

o.f = independent;
console.log(independent()); // logs 15
console.log(o.f()); // logs 37

区别:上面的函数independent如果直接执行,this是指向全局执行环境,那么this.prop是指向我们的全局变量prop的。但是如果将independent设为对象o的一个属性,那么independent中的this就指向了这个实例,同理this.prop就变成了对象o的prop属性。

构造函数

  我们上面讲到了用构造函数创建对象,其实是利用了this的这种特性。在构造函数中,this对象是指向这个构造函数实例化出来的对象。

function Person(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function () {
    alert(this.name);
  };
}

var p1 = new Person('Jesse', 18, 'coder');
var p2 = new Person('Carol',16,'designer');

当我们实例化Person得到p1的时候,this指向p1。而当我们实例化Person得到p2的时候,this是指向p2的。

利用call和apply

  当我们用call和apply去调用某一个函数的时候,这个函数中的this对象会被绑定到我们指定的对象上。而call和apply的主要区别就是apply要求传入一个数组作为参数列表。

function add(c, d) {
  return this.a + this.b + c + d;
}

var o = { a: 1, b: 3 };

// 第一个参数会被绑定成函数add的this对象
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

// 第二个参数是数组作为arguments传入方法add
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

在bind方法中

  bind方法是 存在于function的原型中的 Function.prototype.bind,也就是说所有的function都会有这个方法。但我们调用某一个方法的bind的时候,会产生一个和原来那个方法一样的新方法,只不过this是指向我们传得bind的第一个参数。

function f() {
  return this.a;
}

var g = f.bind({ a: "azerty" });
console.log(g()); // azerty

var o = { a: 37, f: f, g: g };
console.log(o.f(), o.g()); // 37, azerty

在dom元素事件处理器中

  在事件处理函数中,我们的this是指向触发这个事件的dom元素的。

HTML代码

<html>
<body>
  <div id="mydiv" ></div>
  <script type="text/javascript" class="lazy" data-src="essence.js"></script>
</body>
</html>

JavaScript代码

function click(e) {
  alert(this.nodeName);
}

var myDiv = document.getElementById("mydiv");
myDiv.addEventListener('click', click, false);

当我们点击页面那个div的时候,毫无疑问,它是会显示DIV的。

Javascript基之js面向对象的示例分析

详解prototype
  prototype即原型,也是Javascrip中一个比较重要的概念。在说原型之前呢,我们需要回顾一下之前的构造函数模式。在我们用构造函数去创建对象的时候主要是利用了this的特性。

function Person(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function () {
    alert(this.name);
  };
}

var p1 = new Person('Jesse', 18, 'coder');
var p2 = new Person('Carol', 17, 'designer');

我们上面还讲到了当用Person实例化p1的时候Person中的this是指向p1的,当实例化p2的时候呢,this是指向p2的。那也就是说,p1和p2中的sayName虽然起到了同样的作用,但是实际上他们并非是一个函数。

Javascript基之js面向对象的示例分析

也就是说他们内存堆中是存在多份拷贝的,而不是在栈中引用地址的拷贝。先不说这符不符合面向对象的思想,至少这对于内存来说也是一种浪费。而解决办法就是我们要讨论的原型。

什么是原型

  在Javascript中的每一个函数,都会有一个原型对象,这个原型对象和我们普通的对象没有区别。只不过默认会有一个constructor属性指向这个函数。 同时,所有这个函数的实例都会有一个引用指向这个原型对象。如果不太清楚,那就看看下面这张图吧:

Javascript基之js面向对象的示例分析

以上就是构造函数,构造函数原型,以及实例之间的关系。以我们的Person构造函数为例,所有Person的实例(p1,p2)都舒服一个prototype属性指向了Person构造函数prototype对象。如此一来,我们就可以把方法写在原型上,那么我们所有的实例就会访问同一个方法了。

function Person(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;

  Person.prototype.sayName = function () {
    alert(this.name);
  }
}
var p1 = new Person('Jesse', 18, 'coder');
var p2 = new Person('Carol', 17, 'designer');

alert(p1.sayName == p2.sayName); // true

什么是原型链

  大家还记得作用域链么?如果不记得,请自觉到第二篇中去复习(作用域和作用域链)。简单的来说,我们在一个执行环境中访问某个变量的时候如果当前这个执行环境中不存在这个变量,那么会到这个执行环境的包含环境也就是它的外层去找这个变量,外层还找不到那就再外一层,一直找到全局执行环境为止,这就是作用域链。而原型链有点类型,只不过场景换到了我们的对象实例中,如果我在一个实例中找某一个属性,这个实例中没有,那就会到它的原型中去找。记住,我们上面说了,原型也是一个对象,它也有自己的原型对象,所以就行成了一个链,实例自己的原型中找不到,那就到原型的原型对象中去找,一直向上延伸到Object的原型对象,默认我们创建的函数的原型对象它自己的原型对象是指向Object的原型对象的,所以这就是为什么我们可以在我们的自定义构造函数的实例上调用Object的方法(toString, valueOf)。

Javascript基之js面向对象的示例分析

利用原型实现继承

  其实我们上面已经讲了继承在Javascript中的实现,主要就是依靠原型链来实现的。所有的实例是继承自object就是因为在默认情况下,我们所有创建函数的原型对象的原型都指向了object对象。同理,我们可以定义自己的继承关系。

function Person(name, age, job) {
  this.name = name;
  this.age = age;
}
Person.prototype.sayName = function () {
  alert(this.name);
}

function Coder(language){
  this.language = language;
}
Coder.prototype = new Person(); //将 Coder 的原型指向一个Person实例实现继Person
Coder.prototype.code = function () {
  alert('I am a '+ this.language +' developer, Hello World!');
}

function Designer() {
}
Designer.prototype = new Person(); //将 Desiger 的原型指向一个Person实例实现继Person
Designer.prototype.design = function () {
  alert('其实我只是一个抠图工而已。。。。');
}

var coder = new Coder('C#');
coder.name = 'Jesse'; 
coder.sayName(); //Jesse
coder.code();   // I am a C# developer, Hello World!

var designer = new Designer();
designer.name = 'Carol';
designer.sayName(); // Carol
designer.design();  // 其实我只是一个抠图工而已。。。。

原型链中的问题

  由于原型对象是以引用的方式保存的,所以我们在赋值的时候要特别注意,一不小心就有可能把之前赋的值给赋盖了。比如上面的代码中,我们先写原型方法,再实现继承,那我们的原型方法就没有了。

function Coder(language){
  this.language = language;
}
Coder.prototype.code = function () {
  alert('I am a '+ this.language +' developer, Hello World!');
}
Coder.prototype = new Person(); //这里会覆盖上面所有的原型属性和方法
var coder = new Coder('C#');
coder.name = 'Jesse';
coder.sayName();
coder.code();   // 这里会报错,找不到code方法。

以上是“Javascript基之js面向对象的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Javascript基之js面向对象的示例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java面向对象之数组的示例分析

这篇文章主要介绍Java面向对象之数组的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Java面相对象之数组1.一维数组1.数组的说明:相同类型数据的组合。说明:①数组是引用数据类型,数组的元素可以是基本数据
2023-06-02

Java面向对象之多态的示例分析

这篇文章主要介绍Java面向对象之多态的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!/**知识点: 多态 Polymorphism1. 对象的多态性分为三种: 方法的重载, 方法的覆盖, 对象的向上向下转型
2023-06-02

java面向对象的示例分析

这篇文章主要介绍了java面向对象的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、Java特效1、简单性人们希望构建一个无须深奥的专业训练就可以进行编程的系统,并
2023-06-29

Java基础之面向对象机制底层实现的示例分析

这篇文章主要介绍Java基础之面向对象机制底层实现的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允
2023-06-14

Python面向对象基础举例分析

本篇内容主要讲解“Python面向对象基础举例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python面向对象基础举例分析”吧!1. 面向对象oop了解# ### oop 面向对象的程序开
2023-06-21

Python面向对象中类和对象的示例分析

这篇文章主要介绍了Python面向对象中类和对象的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。什么是面向对象编程?我们是不是听过面向过程,拿来放在一起对比就比较好理
2023-06-22

python面向对象开发的示例分析

这篇文章主要介绍了python面向对象开发的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Python 面向对象Python从设计之初就已经是一门面向对象的语言,正因
2023-06-29

Python面向对象和类的示例分析

这篇文章主要为大家展示了“Python面向对象和类的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python面向对象和类的示例分析”这篇文章吧。一、两大编程思想二、类与对象简单举例:p
2023-06-26

Java面向对象之匿名内部类的示例分析

小编给大家分享一下Java面向对象之匿名内部类的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!/**知识点: 匿名内部类题目: 摩托车上装有警报器,当有人
2023-06-02

PHP5面向对象的问题的示例分析

这期内容当中小编将会给大家带来有关PHP5面向对象的问题的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。大家也许对PHP5面向对象已经不再陌生,虽然对一些问题的反映虽然加强了很多,但还有很多东西比
2023-06-17

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录