一,程序中的foo,bar,baz
Stackoverflow
函数,变量,文件的名字代指。本身没有特别的用途和意义,常被称之为“伪变量”。
foo:first object oriented 第一个面向对象
bar:binary arbitrary reason 任意二进制原因
baz
二,函数使用步骤
1.声明函数的过程是对某些特定功能过程的封装过程
也可以使用默认提供的或者其他三方库定义好的函数。
2.声明和调用函数
function函数名() {
函数封装的代码
}
小括号是用来传参数的,小括号后往往要跟一个空格作为代码规范。
3.函数在没有调用的情况下是不运行的
三,函数的参数
1.函数
把具有独立功能的代码块组织为一个小模块,在需要的时候调用。
function printinfo(name,age,height){
console.log(`my name is ${name}`)
console.log(`my age is ${age}`)
console.log(`my hright is ${height}`)
}
printinfo("why",18,1.88)
Printinfo("kobe",30,1.98)
函数的参数,增加函数的通用性,针对相同的数据处理逻辑,能够适应更多的数据。
- 在函数内部,把参数当作变量使用,进行需要的数据处理。
- 在函数调用时,按照函数定义的参数顺序,把希望在函数内部处理的数据,通过参数传递。
形参parmaters:定义的变量,例如name,age,height
实参arguments:调用时传入的实际参数
练习1:给某人打招呼
function sayHello(name){
console.log(`Hello ${name}`)
}
sayHello("kobe")
sayHello("James")
sayHello("Curry")
练习2:给某人唱生日歌
function singBirthdaySong(name) {
console.log("happy birth day to you")
console.log("happy birth day to you")
console.log(`happy birth day to ${name}`)
console.log("happy birth day to you")
}
singBirthdaySong("Kobe")
24.函数的返回值
使用return来返回结果,如果使用return,函数立即终止执行。如果没有使用return或者没有return一个具体的值,返回值undefined,例如foo。
var result = prompt()
在这里,用promt返回的值用var做了一个接收。
function SayHello(name) {
console.log(`Hi ${name}`)
}
var foo = SayHello("Kobe")
console.log("foo:",foo)
eg1:传入宽高,计算矩形的面积
function getRectangleArea(width,height){
return width * height
}
var area1 = getRectangleArea(20,30)
console.log("area1":area1)
var area2 = getRectangleArea(50,60)
console.log("area2":area2)
eg2:传入半径,计算圆形的面积
function getCircleaAea(radius){
return (Math.PI * radius * radius).toFixed(2)
}
var area3 = getciclearea(10)
console.log("area3",area)
var area4 = getciclearea(25)
console.log("area4",area)
eg:定义一个函数,传入n,计算1~n的数字和
function sumN(n){
1.对n的判断
if (n <= 0)
console,log(`您传入的${n}是有问题的`)
return
}
2,真正对1~n的数字进行计算
var total = 0
for (var i = 1 ; i <= n ; i++) {
console.log(i)
toral += i}
return total
}
var result2 = sumN(5)
var result2 = sumN(10)
console.log(`result1:${result1}`,`result2:${result2}`)
var result3 = sumN(-10) 无法计算
console.log("result3:,result3)
四,封装一个工具函数,对数字进行格式化
传入一个数字,可以根据数字转化成显示为亿,万文字显示的文本
var playCount1 = 13687
var playCount2 = 5433322
var playCount3 = 8766633333
function formatcount(count) {
var result = 0
if (count >= 10_0000_0000){
result = Math.floor (count / 1_0000_0000) + "亿"
} else if (count >= 10_0000) {
result = Math.floor (count / 1_0000) +"万“
} else {
result = count
}
return result
}
console.log(formatCount(playCount1))
console.log(formatCount(playCount2))
console.log(formatCount(playCount3))
五,函数的arguments
类数组对象,不是一个数组,但是和数组的用法看起来很相似。
function foo(name,age){
console.log("传入的参数",name,age)
console.log(arguments[0])
console.log(arguments[2])
// 对arguments进行遍历
for (var i = 0; i < arguments.length; i++)
console.log(arguments[i])
}
foo("why",18,1.88,"广州市")
不定义传入参数的个数
function sum() {
var total = 0
for (var i = 0;i < arguments.length; i++){
console.log(arguments[i])
total += num
}
}
console.log(sum(10,20))
console.log(sum(10,20,30))
console.log(sum(10,20,30,40))
六,函数中调用函数
function foo() {
console.log("foo函数被执行了”)
foo()
}
递归 (Recursion )调用的认识:函数自己调用自己,结束必须有条件,代码简洁。默认情况下会产生无限调用,栈内存最终会被耗尽 ,代码会报错。被称为递归。
eg:封装一个可以实现x的n次幂的函数
function pow1(x,n){
return x ** n
}
math里的默认函数:
console.log(math.pow(2,3))
7.2:for循环的实现方式
function pow2(x,n){
var result = 1
for (var i = 0; i < n ; i++){
result *= x
}
return result
}
console.log(pow2(2,3))
7.3 递归的实现思路
function pow (x,n){
在某一个条件下,让它不再继续调用
if ( n === 1 ) return x
return x * pow(x,n-1)
}
console.log(pow (2,3))
递归的性能较低,会占据过多的栈内存。
因为pow(x,n) === x * pow(x,n-1)
7.4 用递归来实现斐波那契数列
function fibonacci(n){
if (n === 1 || n === 2) return 1
function fibonacci(n-1) + fibonacci(n-2)
}
console.log(fibonacci(5))
console.log(fibonacci(10))
因为n = (n-1)+(n-2)
用for循环来实现斐波那契数列
function fibonacci (n)
if ( n === 1 || n === 2) return 1
var n1 = 1
var n2 = 1
var result = 0
for (var i = 3 ; i <= n ; i++){
result = n1 + n2
n1 = n2
n2 = result09
}
return result
}
console,log(fibonacci(4))
八,局部变量和外部变量
8.1.作用域:表示一些标识符的作用有效范围
8.2.es5之前没有块级作用域,
var定义的变量,在外部可以访问,没有自己的作用域的。变量作用域?
for循环,if语句的代码块也是没有自己的作用域的,可以全局访问。
for (var i = 0 ; i < 3 ;i ++){
var foo= "foo"
}
console.log("for循环外面访问foo:",foo) // 可以访问
console.log("for循环外面访问i:",i) // 这时i === 3;
8.3.es5之前只有函数代码块会形成自己的作用域
在函数内部定义的变量,外部是访问不到的。
而let,const也是有块级作用域的。
function test(){
var bar = "bar"
}
test()
console.log("test函数外面访问bar:",bar) // 无法访问
8.4 函数有自己的作用域,函数内部定义的变量只有函数内部能访问到
function sayHello(){
var nickname = "kobe"
}
sayHello()
Console.log("函数外面访问变量",nickname) // 变量放入函数内部就无法从外部访问了
8.5 在函数内部再定义一个函数,在函数内部的函数可以访问到函数内部的变量
function sayHello(){
var nickname = "kobe"
function hi() {
console.log("hi function")
}
hi() // 在函数内部的函数可以访问到函数内部的变量
}
sayHello()
九,全局-布局-外部变量理解
9.1 全局变量(global variable):
在全局中定义一个变量,那么这个变量是可以在定义之后的任何范围内被访问,那么这个变量被称之为是一个全局变量,例如变量
var messaege = "Hello World"
//在function,function内部的function,if,for都可以访问到
//在前面访问是有点违背的,访问会出现undefined,和var的作用域提升有关,将var改成let即可
9.2 局部变量(local variable):
在函数内部定义的变量,只有在函数内部才能进行访问,例如函数内部的变量
var messaege = "Hello World"
function hi {
var nickname = "coderwhy"
console.log("coderwhy",coderwhy) // 在函数内部可以访问函数内部的变量
console.log("hi中访问message,message") // 访问当前函数外部的变量,称为外部变量
}
hi()
9.3 外部变量(outer variable):
在函数内部去访问函数之外的变量,我们访问的变量称之为外部变量
代码块同上;
9.4 变量的访问顺序-作用域链:
从局部变量–> 外部变量 --> 全局变量
十,函数表达式function expressions
function foo() {
} // 函数声明
var bar = function(){
console.log("bar函数被执行了“)
}
bar() // 函数表达式
注意:function关键词后面没有命名。
函数声明 和 函数表达式的区别:
函数声明会被提升到作用域最前面。
函数声明运行规则:
函数声明只能出现在程序和函数体内,不能出现在block中,例如不能出现在if、while和for语句中,因为block中只能包含statement语句。
十一,JS头等函数—功能强大
函数可以作为别的函数的参数,函数的返回值,赋值给变量变或存储在数据结构中。
一等公民:函数可以作为别的函数的参数、函数的返回值,赋值给变量或存储在数据结构中
回调函数:一个函数作为另外一个函数的参数,称之为回调函数,也称为高阶函数
匿名函数:如果在传入一个函数时,我们没有指定这个函数的名词或者通过函数表达式指定函数对应的变量,那么这个函数称之为匿名函数
11.1 函数可以被赋值给变量
var foo1 = function(){ //函数表达式写法是表现之一
console.log("foo1函数被执行“)
}
foo1()
11.1.2 让函数在变量之间来回传递
var foo1 = function(){ //函数表达式写法是表现之一
console.log("foo1函数被执行“)
}
foo1()
var foo2 = foo1 // 赋值
foo2() // 调用
11.1.3 函数可以作为另外一个函数的参数
var foo1 = function(){
console.log ("foo1函数被执行")
}
function bar(fn){
console.log("fn:",fn)
fn()
}
bar (foo1) // 用bar传入参数 var fn = foo1? 即foo1
11.1.4 函数可以作为另外一个函数的返回值
function sayHello(name) {
function hi() {
console.log ("hi" + name)
}
return hi
}
var fn = sayHello("kobe") // 柯里化
fn() // 这里调fn()意味着调hi()
11.1.5 函数存储在另外一个数据结构中
var obj = {
name = "why";
eating:function(){
console.long("eating")
}
}
obj.eating()
//
function bar1(){
console.log("bar1函数被执行“)
}
function bar2(){
console.log("bar1函数被执行“)
}
function bar3(){
console.log("bar1函数被执行“)
}
事件总线的封装
var fns = [bar1,bar2,bar3] // 函数放在数组中 - 事件封装
函数功能强大的编程叫做函数式编程,这种编程范式,js支持函数式编程,swift支持,java就不支持这种写法。最初函数式编程来自于lisp这种语言。
十二,回调函数Callback function
12.1 函数回调的概念理解
通过一个变量调用远地方的函数,称为函数的回调,有时候就是调用自己内部被传入的的函数。
function foo(fn){ //通过fn去调用bar函数的过程,称之为函数的回调
fn() // 调用fn时候就对bar进行执行
}
function bar() {
console.log("bar函数被执行了~“)
}
foo(bar) // 把bar函数以参数的形式传递给了fn,注意写法不可写成foo(bar()),这意味着执行函数
12.2 函数回调的案例-有点难理解!!
function requese(url,callback){
console.log("根据URL向服务器发送网络请求“)
console.log("需求花费较长的时间拿到对应的结果“)
var list = ["javascript","javascript学习","javacript高级编程"]
callback(list) // 异步请求不能直接return出去,callback() 是特殊用法
}
function handleResult(res){ // 在发送请求时候同时传入一个函数
console.log("在handresult中拿到结果:,res)
}
resquest("http://www.baidu.com/abc/getSearchResult",handleResult)
回调函数和异步执行紧密相关
回调函数:接收另外一个函数作为参数.
异步执行:JS碰到比较耗时的操作并不会停在原地一直等待直到函数执行完毕,而是直接执行下一行代码
callback作用:两步走
step1:利用callback关键字将匿名函数传入参数列表
step2:“执行”从参数列表里传递进来的那个函数,可解决上述异步执行的问题.
注意:传入的函数是没有名字的,又叫做匿名函数
12.3 代码重构 — 用了匿名函数
function requese(url,callback){
console.log("根据URL向服务器发送网络请求")
console.log("需求话费较长的时间拿到对应的结果")
var list = ["javascript","javascript学习","javacript高级编程"]
callback(list)
}
传入的函数没有名字,被称为匿名函数
resquest(“url”,function(res){ //传入的函数没有名字,称为匿名函数
console.log("在handleresult中拿到结果",res)})
匿名函数:传入的函数没有名字。
高阶函数:如果函数可以接受/返回另外一个函数。数组中 [].map [].filter [].reduce都是高阶函数。
十三,立即执行函数
1.概念
immediately-invoked function expression(iife立即调用函数表达式)
- 第一部分是定义了一个匿名函数,这个函数有自己的独立的作用域
- 第二部份是(),表示函数被立即执行
function foo {
console.log("foo函数被执行")
}
foo();
最常用的写法:
(function(){
console.log("函数立即被执行")
})()
立即执行函数的参数和返回值
var result = (funciton (name){
console.log("bar函数立刻被执行",name)
return "Hello World"
})(“why”)
console.log(result)
{} 可以表示代码块,使用类型。
()可以控制优先级,控制优先级/函数的调用/函数的参数
[]可以表示定义一个数组/从对象里取值/对象的计算属性
2.应用一
立即执行函数和普通代码的区别:
在立即执行函数中,定义的变量是有自己的作用域的,想从外面访问是访问不到的。
var xmModule = (function(){
var xmModule = {}
var message = "HelloWorld"
console.log(message)
xmModule.message = message
return xmModule
})()
ESmodule
- 防止全局变量的命名冲突(js后来引入了模块化)
应用2
<button class="btn">按钮1<button/>
<button class="btn">按钮2<button/>
<button class="btn">按钮3<button/>
<button class="btn">按钮4<button/>
获取一个按钮来监听点击:
1.拿到html元素
var btnEl = ducument.querySeclector(".btn")
console.log(btnE1)
2.添加事件监听
btnEl.onclick = function() {
console.log("点击了按钮1")
}
获取
var btnEls = document.querySelectorAll(".btn")
for (var i = o; i < btn.lenght ; i++)
var btn = btnEl[i]
btn onclick = function(){
console.log(`按钮${i+1}发生了点击`)
}
- console.log的i是从全局找的,这个时候 i === 4。在ES6中,var换成let,因为let有块级作用域。
var btnEls = document.querySelectorAll(".btn")
for (var i = o; i < btn.lenght ; i++) {
var btn = btnEl[i]
(function(m){
btn onclick = function(){
console.log(`按钮${m+1}发生了点击`)
}
})(i)
- 这里是用立即执行函数提高了console.log的i的优先级。
十四,立即执行函数的其他写法
匿名函数
(function(fn) {
}())
函数声明不能被立即调用,只有函数表达式才可以立即调用。
十五,代码规范
1.在参数和函数名之间没有空格
2.在参数与参数之间有空格
3.大括号和函数名、参数在同一行,前有空格
4.声明变量需要向后缩进两个空格
6.在for/if/while后有一个空格
7.在操作符前后都有空格
8.在语句结束后有分号
9.在类数组对象中的参数之间有空格
10.在逻辑代码块之间有空行
11.else不用换行
12.在内调函数前后有空格
十六,代码调试技巧 debug
在程序里的debugger标识符,就是在代码中打断点的方式。
1,breakpoint:停止执行某一行代码-------->添加debugger。
在程序里的debugger标识符,就是在代码中打断点的方式。
2.watch:监听变量的变化过程。
3,scope:作用域,可见local/闭包/globle。
4.Call Stack:调用栈,记录函数的调用过程。
右侧5个符号:
1/5:resume:只是恢复某个断点上的继续执行
2/5:过掉当前行的代码,继续下一行的代码
3/5into:进入函数内部看看函数是如何执行的
4/5:立即跳出函数
5/5:异步函数:跳过浏览器的源码/匿名函数,into不会跳过