JavaScript学习笔记——函数
2014-03-09 23:48
661 查看
二、函数
1 函数声明与函数表达式
2 立即调用函数
3 arguments对象
4 this指的是谁
5 改变this的指向call与apply
6 执行上下文Context
一系列活动的执行上下文从逻辑上形成一个栈。栈底总是全局上下文,栈顶是当前(活动的)执行上下文。当在不同的执行上下文间切换(退出的而进入新的执行上下文)的时候,栈会被修改(通过压栈或者退栈的形式)。
7 函数执行过程
分为两个阶段:
第一阶段 进入执行上下文
函数的形参:其属性名就是形参的名字,其值就是实参的值;对于没有传递的参数,其值为undefined
函数声明:变量对象的一个属性,其属性名和值都是函数对象创建出来的;如果变量对象已经包含了相同名字的属性,则替换它的值
变量声明:变量对象的一个属性,其属性名即为变量名,其值为undefined;如果变量名和已经声明的函数名或者函数的参数名相同,则不会影响已经存在的属性。
第二阶段 执行代码
8 constructor和prototype
function Person(name) {
this.name = name;
this.sayName = function() {
console.log(this.name);
};
}
var person1 = new Person("Nicholas");
var person2 = new Person("Greg");
console.log(person1.name); // "Nicholas"
console.log(person2.name); // "Greg"
person1.sayName(); // outputs "Nicholas"
person2.sayName(); // outputs "Greg"
9 闭包
一个计数器
修改:
var data = [];
for (var k = 0; k < 3; k++) {
data[k] = (function _helper(x) {
return function () {
alert(x);
};
})(k); // 将 "k" 值传递进去
}
// 现在就对了
data[0](); // 0
data[1](); // 1
data[2](); // 2
提供函数外部访问函数内部变量的一种机制;
保存闭包形成时的上下文环境。
从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。
从实践角度,以下函数才算是闭包:
① 即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回);
② 在代码中引用了自由变量;
10 面试题
1 函数声明与函数表达式
function demo(){}; var demo = function(){};
2 立即调用函数
(function(){})();
3 arguments对象
4 this指的是谁
function sayNameForAll() { console.log(this.name); } var person1 = { name: "Nicholas", sayName: sayNameForAll }; var person2 = { name: "Greg", sayName: sayNameForAll }; var name = "Michael"; person1.sayName(); // outputs "Nicholas" person2.sayName(); // outputs "Greg" sayNameForAll(); // outputs "Michael"
5 改变this的指向call与apply
function sayNameForAll(label) { console.log(label + ":" + this.name); } var person1 = { name: "Nicholas" }; var person2 = { name: "Greg" }; var name = "Michael"; sayNameForAll.call(this, "global"); // outputs "global:Michael" sayNameForAll.call(person1, "person1"); // outputs "person1:Nicholas" sayNameForAll.call(person2, "person2"); // outputs "person2:Greg"
function sayNameForAll(label) { console.log(label + ":" + this.name); } var person1 = { name: "Nicholas" }; var person2 = { name: "Greg" }; var name = "Michael"; sayNameForAll.apply(this, ["global"]); // outputs "global:Michael" sayNameForAll.apply(person1, ["person1"]); // outputs "person1:Nicholas" sayNameForAll.apply(person2, ["person2"]); // outputs "person2:Greg"
6 执行上下文Context
一系列活动的执行上下文从逻辑上形成一个栈。栈底总是全局上下文,栈顶是当前(活动的)执行上下文。当在不同的执行上下文间切换(退出的而进入新的执行上下文)的时候,栈会被修改(通过压栈或者退栈的形式)。
7 函数执行过程
分为两个阶段:
第一阶段 进入执行上下文
函数的形参:其属性名就是形参的名字,其值就是实参的值;对于没有传递的参数,其值为undefined
函数声明:变量对象的一个属性,其属性名和值都是函数对象创建出来的;如果变量对象已经包含了相同名字的属性,则替换它的值
变量声明:变量对象的一个属性,其属性名即为变量名,其值为undefined;如果变量名和已经声明的函数名或者函数的参数名相同,则不会影响已经存在的属性。
第二阶段 执行代码
8 constructor和prototype
function Person(name) {
this.name = name;
this.sayName = function() {
console.log(this.name);
};
}
var person1 = new Person("Nicholas");
var person2 = new Person("Greg");
console.log(person1.name); // "Nicholas"
console.log(person2.name); // "Greg"
person1.sayName(); // outputs "Nicholas"
person2.sayName(); // outputs "Greg"
function Person(name) { this.name = name; } Person.prototype.sayName = function() { console.log(this.name); }; var person1 = new Person("Nicholas"); var person2 = new Person("Greg"); console.log(person1.name); // "Nicholas" console.log(person2.name); // "Greg" person1.sayName(); // outputs "Nicholas" person2.sayName(); // outputs "Greg"
function Person(name) { this.name = name; } Person.prototype = { sayName: function() { console.log(this.name); }, toString: function() { return "[Person " + this.name + "]"; } }; var person1 = new Person("Nicholas"); console.log(person1 instanceof Person); // true console.log(person1.constructor === Person); // false console.log(person1.constructor === Object); // true修正后:
function Person(name) { this.name = name; } Person.prototype = { constructor: Person, sayName: function() { console.log(this.name); }, toString: function() { return "[Person " + this.name + "]"; } }; var person1 = new Person("Nicholas"); var person2 = new Person("Greg"); console.log(person1 instanceof Person); // true console.log(person1.constructor === Person); // true console.log(person1.constructor === Object); // false console.log(person2 instanceof Person); // true console.log(person2.constructor === Person); // true console.log(person2.constructor === Object); // false
9 闭包
一个计数器
var count = (function(){ var num = 0; return function(){ return num++; }; })();
var data = []; for (var k = 0; k < 3; k++) { data[k] = function () { alert(k); }; } data[0](); // 3, 而不是 0 data[1](); // 3, 而不是 1 data[2](); // 3, 而不是 2
修改:
var data = [];
for (var k = 0; k < 3; k++) {
data[k] = (function _helper(x) {
return function () {
alert(x);
};
})(k); // 将 "k" 值传递进去
}
// 现在就对了
data[0](); // 0
data[1](); // 1
data[2](); // 2
提供函数外部访问函数内部变量的一种机制;
保存闭包形成时的上下文环境。
从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。
从实践角度,以下函数才算是闭包:
① 即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回);
② 在代码中引用了自由变量;
10 面试题
var num = 1; var modify = function(){ num = 2; }; modify(); alert(num); function modify(){ num = 3; } modify(); alert(num);
alert(x); // function var x = 10; alert(x); // 10 x = 20; function x() {}; alert(x); // 20
相关文章推荐
- js中的关键字 var
- jsp页面中script代码放置的位置知识整理
- 各种js校验
- Javascript 基础知识
- js设计模式
- 使用匿名函数在回调函数中正确访问JS循环变量
- 使用匿名函数在回调函数中正确访问JS循环变量
- C#中读写JSON风格的配置信息
- JavaScript学习笔记——变量
- JSP页面的五种跳转方法
- javascript 不间断向左滚动图片
- Javascript模块化编程(三):require.js的用法
- javascript 单行向上滚动文字
- javascript tab onclick
- 润乾报表超链接调用js函数
- Javascript模块化编程(二):AMD规范
- js 求时间差
- IE8"开发人员工具"使用详解下(浏览器模式、文本模式、JavaScript调试、探查器)
- Javascript模块化编程(一):模块的写法
- Javascript 定义类或对象