JavaScript(二)(函数)

函数
不能在条件语句中声明函数
name属性返回紧跟在function关键字之后的那个函数名。
length属性返回函数定义中参数的个数。
函数的toString方法返回函数的源码。
如果函数A调用函数B,函数B不会引用函数A的内部变量。

var x = function (){
  console.log(a);
};
function y(f){
  var a = 2;
  f();
}
y(x)
// ReferenceError: a is not defined
//函数x是在函数y体外声明的,作用域绑定外层,因此找不到函数y的内部变量a,导致报错。

函数体执行到return就返回结果,如果没有return,也会返回,返回值为undefined
调用函数:
调用函数传入的参数可以比定义的少,没有传入的为undefined;
调用函数传入的参数也可以比定义函数的参数多,多出的参数不影响;
arguments指向调用函数传入的参数,类似数组但不是数组
rest参数:rest参数是ES6新标准

function(a,b,...rest) {
console.log(a);
console.log(b);
console.log(...rest);
}

rest参数接收多出的全部参数,为一个数组
如果传入的参数比定义的参数多,多出的参数存入数组rest[];
如果传入的参数比定义的少或者刚好和定义的一样多,则rest为一个空数组,不是undefined;
rest参数只能写在最后,前面用...标识;

function foo(a, b, ...rest) {
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// [ 3, 4, 5 ]
foo(1);
// 结果:
// a = 1
// b = undefined
// []

变量作用域
声明在函数中的变量只在该函数内有效:如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量;
不同函数内部的同名变量互相独立,互不影响;
定义在一个函数内部的函数,内部函数可以使用外部函数的变量,外部函数不可以使用内部函数的变量;
变量提升:提升变量的声明到函数的顶部,变量的赋值位置不变;
全局变量:不在函数内声明的变量是全局变量,JavaScript有一个全局对象window,可以以window的属性的方式调用全局变量;顶层函数也可以作为window的方法调用:

var x = 1;
function a() {
console.log("a function");
}
alert(window.x);//1;
alert(x);//1
window.a();//console.log("a funciton");
a();//console.log("a funciton");

可以通过将一个函数赋值给一个变量保存这个函数:

var oldalert = window.alert;//把原来的alert保存在变量oldalert中
window.alert= function() { console.log("a new alert") };//改变了alert函数的用处
alert();//此时执行alert()方法,已经不再弹窗了,可以看到控制台的输出信息
oldalert("the old alert");//因为原来的alert被保存起来了,可以通过oldalert调用原来的方法
window.alert=oldalert;//恢复原来的alert方法
alert("recorver");//原来的alert恢复了

命名空间:
不同JavaScript文件定义的同名全局变量会造成冲突
解决方法:
只命名一个唯一的全局变量,其他的变量作为该全局变量的属性,函数作为该全局变量的方法;
局部作用域:
局部变量的作用域只在声明该变量的函数中
对于for循环内声明的变量,是没有块级作用域的;
一个函数内的for循环内声明的变量,作用域还是这一整个函数
ES6引入了let声明一个变量,有块级作用域
ES6引入了const声明一个常量,有块级作用域,如果试图改变该常量的值,不会报错但是无效
ES6之前不能声明一个常量,通常用变量名大写来表示他是一个常量但是却是可以被修改的(不是真的常量)

this:

var xiaoming = {
    name: '小明',
    birth: 1990,
    age: function () {
        function getAgeFromBirth() {
            var y = new Date().getFullYear();
            return y - this.birth;
        }
        return getAgeFromBirth();//返回值是一个函数的执行结果
    }
};
xiaoming.age(); //调用xiaoming.age方法,返回值是执行一个getAgeFromBirth函数,因为是返回这个函数再调用,所以调用的对象是window,即getAgeFromBirth方法的this指向window(非严格模式下),window.birth是未定义undefined,严格模式下this指向undefined,所以undefined.birth报错

解决方法:
1var that=this;//在一开始将this赋给一个变量,在后面需要this的地方使用这个变量,以保证this的正确指向
2 apply和call:指明this的指向:函数.apply(参数一,参数二);//函数是需要改变其this指向的函数,参数一是this的指向、某个对象,参数二是函数本身所需的参数
函数.call(参数一,参数二);//参数同上,唯一的区别是,apply()把参数打包成Array再传入;call()把参数按顺序传入。

高阶函数:接受一个函数作为它的参数
数组的map方法:arr.map(fn):对数组arr的每一个元素遍历传入函数fn执行,返回一个新的数组
数组的reduce方法:arr.reduce(fn):对数组一个元素执行fn函数,把结果继续和序列的下一个元素做累积计算

function fn(x,y) {
return x*y;
}
var arr=[1,2,3,4];
arr.reduce(fn);//做连乘,相当于f(f(f(1,2),3),4);

数组的filter方法:arr.filter(fn):遍历数组元素,根据fn的返回值如果为真,保留该元素,返回值为假,滤除该元素;返回一个新的数组,不修改原来数组
filter的回调函数fn可以有三个参数element元素本身, index元素索引, self数组本身
数组的sort方法:排序规则比较复杂,sort是一个高阶函数,可以通过给sort传一个自定义的比较函数作为参数,让数组按照我们的规则排序

//从小到大排序
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return -1;
    }
    if (x > y) {
        return 1;
    }
    return 0;
}); // [1, 2, 10, 20]
//从大到小排序
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return 1;
    }
    if (x > y) {
        return -1;
    }
    return 0;
}); // [20, 10, 2, 1]

闭包
函数的返回值是一个函数
在一个函数内部定义一个函数,并将这个内部函数作为外部函数的结果返回,当调用外部函数时,返回的是他的内部函数,需要再次调用这个内部函数执行

function outerfn(o) {
var x = o;
function innerfn() {
return x*x;
}
return innerfn;
}
var inc = outerfn(3);
//var inc ;
//inc=outerfn(3);执行了一次外部函数,x=o=3;返回了一个函数innerfn();这个函数可以使用外部函数的变量,并且记住了他的值
inc();//调用了这个内部函数,返回9

每次调用外部函数都会返回一个新的函数,即使传入相同的参数;
相关参数和变量都保存在返回的函数中,这种程序结构称为“闭包(Closure)”

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            return i * i;
        });//把三个函数放在数组arr中
    }
    return arr;//将数组返回,数组元素是三个相同的函数,因为这个函数没有执行,所以i还是i,仍然是一个引用的变量
}
var results = count();//返回一个数组,数组中有三个相同的函数,i的值变成4
var f1 = results[0];//把数组中的第一个函数赋给f1
var f2 = results[1];//把数组中的第一个函数赋给f2
var f3 = results[2];//把数组中的第一个函数赋给f3
//其实三个函数都是一样的,引用了同一个变量i,这个i已经变成了4
f1();//16,执行这个匿名函数
f2();//16,执行这个匿名函数
f3();//16,执行这个匿名函数

匿名函数的立即执行:

(function (n) {
console.log(n);
})(3);
function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
            }
        })(i));//每次都立即执行这个外部的匿名函数,将对应的i值传给n,n是一个局部变量,只在它自己那个匿名函数中有作用
    }
    return arr;//返回一个数组,数组中有三个匿名函数,这三个匿名函数分别引用他们各自的局部变量n,分别是1,2,3
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 1
f2(); // 4
f3(); // 9

闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。

JavaScript的类型:
number,string,Boolean,object,undefined,function;
123,NaN是number
“haha” 是string
true,false 是boolean
undefined是undefined
Math.abs();是function
[],null和{}是object
用typeof不可以区分出object,null和array
包装对象:
var s = new String('123');//typeof(s):object
var n = new Number(123);//typeof(n):object
var b = new Boolean(true);//typeof(b):object
包装对象将原始值的类型转换成了object
new Number(123)===123//false
不使用new时,
var s = String('123');//typeof(s):string
var n = Number(123);//typeof(n):number
var b = Boolean(true);//typeof(b):boolean
几条规则:
用parseInt()或parseFloat()来转换任意类型到number;
用String()来转换任意类型到string,或者直接调用某个对象的toString()方法;
typeof操作符可以判断出number、boolean、string、function和undefined;
判断Array要使用Array.isArray(arr);
判断null请使用myVar === null;
判断某个全局变量是否存在用typeof window.myVar === 'undefined';
函数内部判断某个变量是否存在用typeof myVar === 'undefined'。
instanceof:

var o = {};
var a = [];
o instanceof Array;//false
a instanceof Array;//true

JSON
JSON实际上是JavaScript的一个子集。
json中的数据类型:
number:和JavaScript的number完全一致;
boolean:就是JavaScript的true或false;
string:就是JavaScript的string;
null:就是JavaScript的null;
array:就是JavaScript的Array表示方式——[];
object:就是JavaScript的{ ... }表示方式。
JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号"",Object的键也必须用双引号""。
JavaScript对象转为json数据格式:
JSON.stringify(参数一,参数二,参数三);
参数一:要转化的对象
参数二:要输出的属性,可以是一个数组,可以省略,也可以是一个函数,对键值对进行处理后返回
参数三:分隔符,可以省略

var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '"W3C" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
};
JSON.stringify(xiaoming,['name', 'skills'], ' ');
//结果:
"{
"name": "小明",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}"

可以给xiaoming定义一个toJSON()的方法,直接返回JSON应该序列化的数据:

var xiaoming = {
name: '小明',
age: 14,
gender: true,
height: 1.65,
grade: null,
'middle-school': '"W3C" Middle School',
skills: ['JavaScript', 'Java', 'Python', 'Lisp'],
toJSON: function () {
return { // 只输出name和age,并且改变了key:
'Name': this.name,
'Age': this.age
};
}
};
JSON.stringify(xiaoming); // '{"Name":"小明","Age":14}'

json格式转JavaScript对象:
JSON.parse(object,[function]);
object是要转化的json,function是可选的一个转换函数
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,225评论 0 4
  • 夜里无聊,去查了回t城的n种可能 从这里到机场需要两小时,偌大个机场走完过完安检登机也得留一个小时。也就是说,看上...
    Chris的另一个世界阅读 239评论 0 0
  • 1.URI我们打开的每个链接都成为一个uri,例如 http://www.baidu.com 第一个代表了约束:h...
    Lazy1阅读 258评论 0 0
  • 经过殊死搏斗的期末考试,假期也接踵而至,来自祖国不同角落的室友也各奔东西。每个寝室都有一个群,平时没有什么动静...
    晴天的小天子阅读 593评论 4 3
  • 小村落 填词:赵雷《成都》 作者:yummy丨循时 岁月河流抚过的 不止脚丫牲口 袅袅炊烟升起的 不止瓦砾房屋 皮...
    循时阅读 1,013评论 9 2