JS — 14 函数相关知识

一、console

console.log( 1 );//1
console.log( "1" );//"1"
console.log( true );//true
console.log( undefined );//undefined
console.log( null );//null
console.log( [ 1 , 2 , 3 , 4 ] );//[ 1 , 2 , 3 , 4 ]
console.log( { name : "小郭"} );//{ name : "小郭"}
console.log( function(){ alert(123) } );//function(){ alert(123) }

在这里插入图片描述

二、return

function aa(){
	console.log( 123 );
}
aa();

此时,控制台打印123,因为函数aa加括号执行了.
在这里插入图片描述

aa();是一个表达式,表达式都有返回值,那么此时aa();的返回值什么?如何得到它的返回值?
在默认情况下,一个函数的返回值为undefined;
我们可以通过一个变量来获得该函数执行后的返回值.

let x = aa();
console.log( x );

在这里插入图片描述
我们可以看到结果,首先aa();调用函数,函数执行,打印123,其次将aa()的返回值赋值给了x,得到undefined,这就说明函数在没有return的情况下返回的都是undefined.

接下来我们给aa这个函数加上一个返回值,并且返回的是一个函数.

function aa(){
	console.log( 123 );
	return function(){
		console.log( 456 );
	}
}
let x = aa();
console.log( x );

在这里插入图片描述
此时我们可以看到aa()返回的是一个函数体,一个函数执行后返回的就是return后面的值.

那么如果我们想在控制台打印出456.该怎么写?

很简单,因为我们将函数aa()执行后的返回值赋值给了x,因此x此时为一个函数,我们只需要执行x这个函数就可以打印出456了.

function aa(){
	console.log( 123 );
	return function(){
		console.log( 456 );
	}
}
let x = aa();
x();

在这里插入图片描述
这样我们就可以引申出下面的写法

function aa(){
	console.log( 123 );
	return function(){
		console.log( 456 );
	}
}
aa()();

在这里插入图片描述
先看结果再来分析,我们可以看到得到的和上面的内容是一样的,那么这么写是什么意思呢?
aa()();
从左往右看
aa()表示调用了aa这个函数,则会打印123,其次还有个返回值,返回的是下面这个函数体

function(){
	console.log( 456 );
}

那么我们在对他进行加括号调用就可以打印出456了.当然上面这个函数体直接加括号去执行是会报错的.因为他是个匿名函数,并且没有参与表达式,没有参与任何表达式的匿名函数都会报错.
那么如何让他自执行,我们只需要将它变成表达式即可,IIFE的方法我在13节有写过.
只有有名函数才可以加括号自执行.

思考:
打印这个函数会得到什么?

function fn(){
	console.log(234);
}
console.log(fn);

在这里插入图片描述
我们看到直接打印函数时为函数体,因为这个函数并没有执行.

function fn(){
	console.log(234);
}
console.log(fn());

如果执行这个函数就是我们上面所说的,此时打印结果如下:
在这里插入图片描述

三、return会立即结束函数

function fn(){
	console.log(1);
	console.log(2);
	console.log(3);
}
fn();

我们执行上述代码可以在控制台得到
在这里插入图片描述
123都被打印了

接下来我们在2的后面加上return看看结果

function fn(){
	console.log(1);
	console.log(2);
	return;
	console.log(3);
}
fn();

在这里插入图片描述
此时,在控制台只打印了1 2
return后面的代码都不会执行了.

得到结论 : return会立即结束函数.

我们还可以和if一起使用,但是要注意,return只对函数起作用

下面的代码是当if判断为真时才会解析到return

function a(){
	console.log(1);
	console.log(2);
	if( 1 < 2 ){
		return;
	}
	console.log(3);
}

此时if的判断结果为true,执行return,结果如下:
在这里插入图片描述
那么当if的判断结果为false,结果是什么样?
在这里插入图片描述
当判断为false时,此时不会执行return,代码继续向下面解析.打印 1 2 3

四、作用域

在函数 foo_a 里面执行函数 foo_b , foo_b的a是10还是20?

let a = 10;

function foo_b(){
	alert( a );
}

function foo_a(){
	let a = 20;
	foo_b();
}

foo_a();

先看结果
在这里插入图片描述
函数foo_b , a的值为10

那么为什么没有就近原则呢?

因为函数的作用域是定义函数的时候决定的,而不是执行函数的时候决定的,因此 foo_a 和 foo_b 属于同级作用域

五、this指向

在任意作用域里面都有 this 关键词
在同一个作用域里 this 指向是相同的

console.log( this );//window => 顶层对象

function a(){
	console.log( this );//window
}
a();//函数自执行

在这里插入图片描述
控制台打印window,说明这两个this都指向window

那么当我们把上面这个函数赋值给一个点击事件时,this又会指向谁?

function a(){
	console.log( this );//document
}
document.onclick = a;

在这里插入图片描述
当我们点击页面时,打印的是document

接下来我们给对象的属性赋值为函数来看看this指向谁

let xiaoguo = {
	name : "xiaoguo",
	say : function(){
		console.log(this);
	}
};
xiaoguo.say();

在这里插入图片描述
控制台打印出了这个对象

接下来我们可以通过this去使用对象中的属性,如下:
因为this指向xiaoguo这个对象,就可以使用 .操作 去访问name属性,然后进行字符串拼接.

let xiaoguo = {
	name : "xiaoguo",
	say : function(){
		console.log(this);
		console.log("我是" + this.name);
	}
};
xiaoguo.say();

在这里插入图片描述

通过上面的内容我们可以得出以下结论:
1.函数内容 this 指向,不是由定义的时候决定的,而是由执行的时候决定的.
2.函数自执行, this指向window
3.事件被动执行, this指向事件对应的节点,事件指向触发的主体,谁的事件就指向谁
4.对象的方法执行, this就指向这个对象.

六、改变this指向

1.call

function aa(){
	console.log(this);
	}
aa();

首先我们来看看现在this指向的是什么?
在这里插入图片描述
此时this指向的是window
如果我们想让这个函数指向别的我们该怎么写?
这时候我们就可以使用 call 来改变this指向
例如:我们想让它指向document

function aa(){
	console.log(this);
	}
aa.call( document );

在这里插入图片描述
我们只需要用 .操作 的方式写 aa.call( document ); 希望指向谁我们就在这个括号里写上谁.

接下来来看看针对对象的方法

let obj = {
x : 10,
fn : function(){
		console.log( "obj.fn执行了" );
		console.log( this );
	}
};

首先我们要找到函数并执行,这里使用 .操作的方式获取

obj.fn();

在这里插入图片描述
我们可以看到这个函数执行了,并且此时this指向这个对象本身,现在我们来改变this指向

obj.fn.call(document );

在这里插入图片描述
那么这样的方法适用于改变事件中this的指向吗?

2.bind

let name = "xiaoguo";
function a(){
	console.log( this );
}
document.onclick = a.call(name);

这段代码是我们点击时执行函数,执行函数获取this指向,但是我们刷新页面,控制台已经获取了this指向
在这里插入图片描述
这是一种错误写法,call等价于函数自执行,事件还未触发式就已经自执行了,并且再次点击时,控制台不会再打印任何内容了.因为这是为一个返回值undefined,我们相当于把undefined赋值给了点击事件,所以没有用.

这时,我们可以使用新的方法改变事件中this的指向.

document.onclick = a.bind( name );

在这里插入图片描述
用来bind就可以改变事件中this的指向了!

因此我们得到结论:
call : 自执行一次函数,并且改变this指向
bind : 既可以改变函数this指向,又不需要立即执行函数

3.apply

首先我们来看下三种执行情况下this分别指向谁

function fn(){
	console.log( this );
}
fn();//window
fn.call( { x : 10 } );//{ x : 10 }
fn.apply( { x : 20 } );//{ x : 20 }

在这里插入图片描述
初步看,apply和call用法类似
那么接下来我们对这个函数进行传参

function fn(a,b){
console.log( a + b );
console.log( this );
}
fn(1,2);
fn.call( { x : 10 },1,2 );
fn.apply( { x : 20 },[1,2] );

1.自执行方法传参不做解释了
2.call传参 : 实参错位对应,允许有多项
3.apply传参 : 所有实参都必须放在数组中,数组中的每一项对应每一项形参

得到结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值