JS高级程序设计笔记(五):引用类型
来源:互联网 发布:win10开始键没反应知乎 编辑:程序博客网 时间:2024/06/08 10:47
Function
函数名就是函数体的引用。可以将函数名作为参数传递给另一个函数,也可以在一个函数内部返回另一个函数,以便在函数体外调用。例如Array.prototype.sort接收一个函数作为参数,该参数规定了比较的规则,如果我们想对数组中的对象按照某个属性来进行排序,可以这样做:
function compareByProperty(property) { return function(o1, o2) { var v1 = o1[property]; var v2 = o2[property]; if (v1 < v2) { return -1; } else if (v1 > v2) { return 1; } else { return 0; } }}var data = [{name: 'lily', age: 10}, {name: 'anna', age: 20}];data.sort(compareByProperty('name'));console.log(data);
1.this
this指向函数据以执行的环境对象。即上下文。是基于函数的执行环境绑定的。
通俗来说,就是调用这个函数的对象。
当函数在被调用的时候(进入执行的上下文时),会生成一个执行环境(excution context),内部有一个属性[scope]指向作用域链,作用域链中的每一项指向一个变量对象(variable object),变量对象中维护了当前函数自身的变量,并且此时活动对象会自动取得this和arguments的值。搜索这两个值只会搜索自身的变量对象,不会沿着作用域链进行搜索。
必须是在一个函数内部定义了一个函数,内部函数才能访问外部函数的变量对象,如果函数是在外部定义但被另一个函数调用了,是不能访问外部函数的变量对象的。
也就是说作用域链的生成和函数定义的位置有关,而this与arguments的值是与函数被调用的环境有关。
‘以下部分参考《JS权威指南》’:
函数的调用形式有:
- 函数
- 方法
- 构造函数
- 通过call和apply间接调用
通常作为函数来调用的时候不会使用this,但可以通过this来判断是否是严格模式。
this是关键字,不是变量,不能赋值。嵌套的函数不会从外部函数中继承this值,如果嵌套函数作为函数调用,this值为window或undefined(严格模式)。
function outter() { console.log('I am outter function!'); function inner() { console.log('I am inner function'); console.log( this === window ); //非严格模式true } inner();}
因此不要觉得嵌套函数的this指向调用外层函数的上下文或者是外层函数,要取得外层函数的this,需要将this保存到一个变量中。
2.arguments.callee指向当前执行的函数;
arguments.callee.caller指向调用当前函数的函数,如果当前函数处于全局作用域中,则caller为null.
3.call和apply
call和apply可以扩充作用域,使得对象和方法不需要有耦合关系。
4.闭包
作用域链和变量对象
函数在进入执行环境(开始调用还未执行到具体语句)时候,会产生一个excution context其中有一个属性[scope]指向了作用域链,而这个作用域链中的每一项又指向了可访问到的变量对象。
变量对象保存了当前执行环境中可访问到的变量,当函数被调用时有arguments、形参、通过function声明的局部函数是具有具体的值的,而其他通过var声明的变量一开始是undefined,直到执行到当前的语句才被赋予具体的值。闭包
闭包就是可以访问到外部函数中变量的函数,即在闭包的作用域链中持有对外部函数变量对象的引用。当外部函数执行完毕后,其作用域链被销毁,如果返回的闭包还存在,则仍然持有对外部函数的变量对象的引用。因此使用闭包是很消耗内存的。
此外,闭包只能取得包含函数中任何变量的最后一个值。在闭包中引用某个变量时,会沿着作用域链在变量对象中进行搜索。
例如:
function createFun() { var result = []; for (var i = 0; i < 10; i++) { result[i] = function() { console.log(i); }; } return result;}var res = createFun();res[0](); //10
result数组中存了10个函数并返回了,可以在外部使用。当这些内部函数调用的时候,执行到console.log(i)时会从变量对象中搜寻该标识符,在自己的变量对象中没有找到,就会沿着作用域链向上查找外部函数的变量对象,现在,在外部函数的变量对象中是这样的内容:
VO:{ result: [//10个匿名函数的引用], i: 10}
此时i已经为10了。
可以在外部再包裹一层,来保存每一次的i值:
function createFun() { var result = []; for (var i = 0; i < 10; i++) { result[i] = function(num) { return function() { console.log(num); }; }(i); } return result;}var res = createFun();res[1](); //1
当调用某个闭包函数resindex时,需要访问num变量,此时会沿着作用域链进行搜索,闭包的作用域链是这样的:
VO res[index]: { //nothing}VO 包裹res[index]的匿名函数: { arguments: num, num: i //是指当前的i,每次循环当前的i都被保存下来}VO createFun: { result: [//10个匿名函数的引用], i: 10}
因此当res[index]沿着作用域链搜索时,会在包裹它的匿名函数的变量对象中找到num,而这个num的值是对应的i的值。
闭包中的this:
每个函数被调用时,其活动对象自动获得this和arguments,在搜索时只搜索自己的活动对象,所以闭包不能获得外部函数的这两个值。而闭包通常是在全局环境中调用,因此闭包内部的this通常是指window。
5.块级作用域
JS中对于重复声明的变量会视而不见。
立即执行的匿名函数可以模拟块级作用域,这样可以避免向全局环境中增加过多的变量。
6.私有变量
在函数内部定义局部变量和局部函数,然后返回一个闭包,在这个闭包中对局部变量和局部函数进行访问。闭包是外部访问局部变量/函数的唯一入口,该闭包称作特权函数。特权函数有两种形式:
- 作为构造函数的方法:
function Func() { var privateVar = ...; function privateFunc() {} this.publicMethod = function() { privateVar++; return privateFunc(); };}
该方式的缺点是,每个实例都要创建一个自己的方法。
- 静态私有变量
(function() { var privateVar = ...; function privateFunc() {} MyObject = function() {}; //构造函数 MyObject.prototype.publicMethod = function() {//原型增强复用 privateVar++; return privateFunc(); };})();
该方式需要一个全局的构造函数(此处只能用函数表达式),并在原型中定义特权方法,该特权方法是一个闭包,能够取得外部函数的私有变量和函数。该方式MyObject的所有实例共享私有变量和私有函数。
注意此处的MyObject虽然是一个全局变量,但该构造函数的声明仍然是在匿名函数内部进行的,因此,在该构造函数内部也是可以访问到外部匿名函数的私有变量的。注意闭包的定义是:
在一个函数内部定义了另一个函数,就创建了闭包
- 模块模式
指为单例增加私有变量和特权方法:
var singleton = function() { var privateVar = ...; function privateFunc() {} return { publicProperty: ..., publicMethod: function() { privateVar++; return privateFunc(); } };}();
这里的单例都是Object的实例。
- 增强的模块模式
适用于单例必须是某个类的实例:
var singleton = function() { var privateVar = ...; function privateFunc() {} var obj = new MyObject(); //特定的类型实例 obj.publicProperty = ...; obj.publicMethod = function() { privateVar++; return privateFunc(); }; return obj;}();
Array
- JS高级程序设计笔记(五):引用类型
- JS高级程序设计(三):引用类型
- 《js高级程序设计》学习笔记--5.引用类型
- JS高级程序设计5-引用类型
- JavaScript高级程序设计笔记-引用类型
- 五、引用类型[js笔记]
- 笔记:js高级程序设计第五章,函数的引用类型与基本类型
- JavaScript高级程序设计(引用类型)
- JavaScript高级程序设计学习笔记——引用类型2Function类型(重要)
- Javascript高级程序设计第二版第五章--引用类型--笔记
- JavaScript高级程序设计学习笔记——引用类型1
- javascript 高级程序设计笔记(五)
- 《JavaScript高级程序设计 第三版》学习笔记 (三)引用类型详解
- 《JavaScript高级程序设计》笔记——chapter5 引用类型(Object/Array)
- 《JavaScript高级程序设计 第三版》学习笔记 (三)引用类型详解
- 《JavaScript高级程序设计 第三版》学习笔记 (三)引用类型详解
- js 高级程序设计笔记
- JS高级程序设计-笔记
- ubuntu16.04用root用户登陆图形界面
- Node.js-前后端开发必备
- 构造方法的个人见解
- web前端面试问题及答案
- 3.用遗传算法将随机产生的字母序列变为短语“to beor not to be”。要求输出每一代最好的字串。
- JS高级程序设计笔记(五):引用类型
- VS中的路径宏 vc++中OutDir、ProjectDir、SolutionDir
- JSP指令详解
- Java学习之路--封装
- 5*.使用模拟退火算法解决“费马点”问题
- Spark Streaming从1.4.1升级至2.0.0-preview遇到的问题汇总
- MSSQL 游标使用
- C语言基础教学——认识C语言编译环境(第二课)
- jsp快捷键