解析JavaScript面向对象概念中的Object类型与作用域


Posted in Javascript onMay 10, 2016

引用类型

引用类型主要包括:Object 类型、Array 类型、Date 类型、RegExp 类型、Function 类型等等。

引用类型使用时,需要从它们身上生成一个对象(实例)。也就是说,引用类型相当于一个模版,当我们想要用某个引用类型的时候,就需要用这个模版来生成一个对象来使用,所以引用类型有时候也称作对象定义。

例如,我们需要生成一个 person 对象,来定义某人的个人信息和行为,那么我们就需要依赖 Object 类型:

var person = new Object();
person.name = "jiangshui";
person.sayName = function(){
  console.log(this.name);
}

上面的这个 person 对象,通过 new 操作符使用 Object 类型这个“模版”定义。之后就可以对这个对象添加属性 name 和方法 sayName 了。属性和方法是 Object 类型具有的“功能”,所以通过 Object 等引用类型创建的对象就可以用这个了。

创建对象不一定非得需要用 new 操作符,有一些类型可以简化的创建,例如创建一个上面那样的 Object 类型的对象,也可以使用下面两种方法:

var person = {};
person.name = "jiangshui";
person.sayName = function(){
  console.log(this.name);
}

var person = {
  name : "jiangshui",
  sayName : function(){
    console.log(this.name);
  }
};

{}操作符的功能就跟 new Object() 一样,简化了操作。上面两种写法也有一些区别,第一种是“追加”,也就是在之前的定义中,继续添加属性或者方法,如果之前已经存在了同名属性方法,则会覆盖。而第二种是“取代”,就是不管前面是否定义 person 对象的属性和方法,这个方法会用新定义的内容,整个替换掉之前定义的。因为引用类型生成的对象,是储存在内存中的一块区域,然后将其指针保存在某变量中(person),第二种写法,是生成了一个新对象(新内存区域),然后将 person 变量指向了新内存区域,所以就把之前的取代了。了解这一点对后面理解,至关重要。

其他引用类型的用法大致一致,例如 Array 类型,也可以用 [] 来生成对象,或者直接定义。生成数组对象之后,就可以按照数组的格式存储信息内容,此外对象会得到 Array 类型中定义的那些方法,例如 push、shift、sort 等等,就可以调用这些方法,例如:

var colors = [];
colors.push('red','green');
console.log(colors);

上面代码就是通过 Array 类型创建一个数组类型的对象,然后调用 Array 类型里面之前定义的 push 方法,向对象里面添加了 red 和 green 两个值,最后在控制台打印出来,就可以看到了。

call 和 apply 方法

这两个方法是 Function 类型提供的,也就是说,可以在函数上面使用。call 和 apply 方法的功能一样,就是可以扩充函数运行的作用域,区别就在于使用 call 的时候,传递给函数的参数必须逐个列举出来,而 apply 方法却不用。这样可以根据自己函数的要求来决定使用 call 或者 apply。

扩充函数运行的作用域是什么意思?举个例子你就明白了。

你可以这样理解,函数被包裹在一个容器(作用域)里面,在这个容器里面存在一些变量或者其他东西,当函数运行,调用这些变量等,就会在当前容器里面找这个东西。这个容器其实外面还包裹了一个更大的容器,如果当前小容器没有的话,函数会到更大的容器里面寻找,依次类推,一直找到最大的容器 window 对象。但是如果函数在当前小容器里面运行的时候,小容器里面有对应变量等,即便是大容器里面也有,函数还是会调用自己容器里面的。

而 call 和 apply 方法,就是解决这个问题,突破容器的限制。就前面例子:

var person = {
  name : "jiangshui",
  sayName : function(){
    console.log(this.name);
  }
};

打开 Chrome 的 Console 之后,粘贴进去执行一下,之后再执行 person.sayName() 可以看到

解析JavaScript面向对象概念中的Object类型与作用域

这时候,person 就是一个容器,其中创建了一个 sayName 方法(函数),执行的时候,必须在 person 作用域下面执行。当在最下面直接执行的时候,也就是在 window 的作用域下面执行会报错 not defined,因为 window 下面没有定义 sayName 方法。而里面的 this 指针,是一个比较特殊的东西,它指向当前作用域,this.name 的意思,就是调用当前作用域下面的 name 值。

下面我们为 window 对象添加一个 name 属性:

window.name = "yujiangshui";

或者直接

name = "yujiangshui";

因为 window 是最大的容器,所以 window 可以省略掉,所有定义的属性或者变量,都挂靠到 window 上面去了,不信可以看:

解析JavaScript面向对象概念中的Object类型与作用域

那现在我们就想在 window 这个大容器下面,运行 person 小容器里面的 sayName 方法,就需要用 call 或 apply 来扩充 sayName 方法的作用域。执行下面语句:

person.sayName.call(window);

或者

person.sayName.call(this);

输出的结果都是一样的,你也可以换用 apply 看看效果,因为这个 demo 太简单的,不需要传递参数,所以 call 和 apply 功能效果就完全一致了。

解析JavaScript面向对象概念中的Object类型与作用域

解释一下上面代码,sayName 首先是 Function 类型的实例,也就具有了 call 方法和 apply 方法,call 和 apply 方法既然是 Function 类型的方法,所以就需要用这种方式调用 person.sayName.call(window) 而不是什么 person.sayName().call(window) 之类的。

然后 call 和 apply 方法的参数,就是一个作用域(对象),表示将前面的函数在传递进去的作用域下面运行。将 window 这对象传递进去之后,sayName 方法中的 this.name 指向的就是 window.name,于是就扩充了作用域。

为什么传递 window 和 this 都是一样的效果?因为我们当前执行这个函数的位置是 window,前面说过 this 指针指向的是当前作用域,所以 this 指向的就是 window,所以就等于 window。

Javascript 相关文章推荐
一个JS翻页效果
Jul 23 Javascript
JavaScript中几个重要的属性(this、constructor、prototype)介绍
May 19 Javascript
ECMAScript6的新特性箭头函数(Arrow Function)详细介绍
Jun 07 Javascript
javascript手风琴下拉菜单实现代码
Nov 12 Javascript
jQuery禁用键盘后退屏蔽F5刷新及禁用右键单击
Jan 22 Javascript
jquery插件jquery.LightBox.js实现点击放大图片并左右点击切换效果(附demo源码下载)
Feb 25 Javascript
详谈$.data()的用法和作用
Feb 13 Javascript
JS简单获取当前日期时间的方法(如:2017-03-29 11:41:10 星期四)
Mar 29 Javascript
es6学习笔记之Async函数基本教程
May 11 Javascript
用javascript获取任意颜色的更亮或更暗颜色值示例代码
Jul 21 Javascript
解决cordova+vue 项目打包成APK应用遇到的问题
May 10 Javascript
mpvue实现小程序签到金币掉落动画(api实现)
Oct 17 Javascript
JavaScript根据CSS的Media Queries来判断浏览设备的方法
May 10 #Javascript
JavaScript中的原型prototype完全解析
May 10 #Javascript
简单解析JavaScript中的__proto__属性
May 10 #Javascript
Web Uploader文件上传插件使用详解
May 10 #Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
May 10 #Javascript
JS上传组件FileUpload自定义模板的使用方法
May 10 #Javascript
使用jQuery处理AJAX请求的基础学习教程
May 10 #Javascript
You might like
全国FM电台频率大全 - 30 宁夏回族自治区
2020/03/11 无线电
详细介绍PHP应用提速面面观
2006/10/09 PHP
php导出csv文件,可导出前导0实例代码
2016/11/16 PHP
php微信开发之自定义菜单实现
2016/11/18 PHP
php无限极分类实现方法分析
2019/07/04 PHP
PHP+Redis事务解决高并发下商品超卖问题(推荐)
2020/08/03 PHP
找到一点可怜的关于dojo资料,谢谢作者!
2006/12/06 Javascript
调用HttpHanlder的几种返回方式小结
2013/12/20 Javascript
Js判断CSS文件加载完毕的具体实现
2014/01/17 Javascript
javascript+ajax实现产品页面加载信息
2015/07/09 Javascript
理解AngularJs指令
2015/12/10 Javascript
浅析C/C++,Java,PHP,JavaScript,Json数组、对象赋值时最后一个元素后面是否可以带逗号
2016/03/22 Javascript
JavaScript仿微博输入框效果(案例分析)
2016/12/06 Javascript
jQuery+ThinkPHP+Ajax实现即时消息提醒功能实例代码
2017/03/21 jQuery
Angular模板表单校验方法详解
2017/08/11 Javascript
微信小程序实现弹出菜单
2018/07/19 Javascript
全面分析JavaScript 继承
2019/05/30 Javascript
[01:07]DOTA2次级职业联赛 - Fpb战队宣传片
2014/12/01 DOTA
[01:36]DOTA2完美大师赛趣味视频之与队友相处的十万个技巧
2017/11/19 DOTA
Python的Flask框架标配模板引擎Jinja2的使用教程
2016/07/12 Python
python利用paramiko连接远程服务器执行命令的方法
2017/10/16 Python
pycharm 将python文件打包为exe格式的方法
2019/01/16 Python
python 判断文件还是文件夹的简单实例
2019/06/10 Python
Django中使用CORS实现跨域请求过程解析
2019/08/05 Python
详解向scrapy中的spider传递参数的几种方法(2种)
2020/09/28 Python
canvas使用注意点总结
2013/07/19 HTML / CSS
HTML5打开手机扫码功能及优缺点
2017/11/27 HTML / CSS
白俄罗斯大卖场:21vek.by
2019/07/25 全球购物
巴西最大的运动品牌:Olympikus
2020/07/14 全球购物
会计学专业自荐信
2014/06/25 职场文书
水利局群众路线专题民主生活会发言材料
2014/09/21 职场文书
收款委托书
2014/10/14 职场文书
党员干部公开承诺书范文
2015/04/27 职场文书
书法社团活动总结
2015/05/07 职场文书
农村老人去世追悼词
2015/06/23 职场文书
公司员工违法违章行为检讨书
2019/06/24 职场文书