JavaScript 函数(二十一)

77 阅读7分钟

函数

定义和调用

系统函数:

  • parseInt():是将字符串转换为整数。
  • parseFloat():是结果返回一个浮点数。
  • isNan():判断函数是否是NaN(是不是数字),是数字返回false,反之true。
  • eval():是以字符串形式表示js代码串,并回馈执行的结果。

自定义函数

function 函数名(){
	语句
}

还有就是匿名函数 自己调自己

<script type="text/javascript">
	(function(a, b) {
		var c = a * b;
		console.log(c)
	})(2, 50);
</script>

可以当变量用,也可以当方法用

<script type="text/javascript">
	var demo = (function(a, b) {
		var c = a * b;
		console.log(c);
	});
	demo(2, 50); //当方法使用
	console.log(demo); //当变量输出
</script>

调用

//作为函数调用
<script type="text/javascript">
	function f1(a, b) {
		console.log(this) //window
		return a * b;
	}

	var sum = f1(3, 4); // 12
	console.log(sum)
</script>
//作为方法调用
<script type="text/javascript">
	var f1 = {

		name: "zhangsan",

		age: 23,

		f2: function() {
			console.log(this)   //{name: "zhangsan", age: 23, f2: ƒ}
			return this.name + " " + this.age;

			return this;

		}

	}

	f1.f2(); // zhangsan 23
</script>
//使用构造函数调用
<script type="text/javascript">
	function f1(arg1, arg2) {

		this.name = arg1;

		this.age = arg2;

	}

	var x = new f1("zhangsan", 23);
	
	x.name; //返回 zhangsna
	console.log(x.name)
</script>
//作为函数方法调用
<script type="text/javascript">
	var fun;
	
	function f1(a,b){
	
	    return a*b;
	
	}
	
	fun=f1.call(fun , 3 , 4);  //返回 12
	console.log(fun)
</script>

<script type="text/javascript">
	function f1(a,b){
		
	       return a*b;
	
	}
	
	var f2=[3,4];
	
	var f3=f1.apply(f3,f2)  //返回12 
	console.log(f3)
</script>

this

函数内部的this指向

在不使用call、apply、bind的情况下,这些this的指向,当我们调用函数的时候是确定的。调用函数的不同决定了this指向的不同
调用方式this指向
普通函数严格模式下是undefined,正常模式是Window
表达式函数严格模式下是undefined,正常模式是Window
构造函数实例对象
对象方法调用该方法所属的对象
事件绑定方法当前事件所绑定的对象
定时器函数Window
立即执行函数(自调用函数)严格模式下是undefined,正常模式是Window

普通函数

正常模式:this指向Window

<script type="text/javascript">
	function fn () {
	    console.log(this)   //Window {window: Window, self: Window, document: document, name: "", location: Location, …}
	}
	fn();
</script>

严格模式:this不知道指向谁,所以打印undefined

<script type="text/javascript">
	function fn () {
	    'use strict'
	    console.log(this)   //undefined
	}
	fn();
</script>

表达式函数

严格模式下this是undefined,正常模式是Window

<script type="text/javascript">
	var fn = function() {
	    console.log(this)   //Window {window: Window, self: Window, document: document, name: "", location: Location, …}
	}
	fn();
</script>

构造函数

构造函数的this指向实例对象,下例指向实例对象fn

<script type="text/javascript">
	function fn(name) {
	    this.name=name;
	    console.log(this)   //fn {name: "constructor function"}
	}
	var fn = new fn('constructor function');
</script>

对象方法调用

对象调用自身方法时的this指向该方法所属的对象

<script type="text/javascript">
	var obj = {
	    name:'zhangsan',
	    say:function() {
	        console.log(this)
	    }
	}
	obj.say() //obj   {name: "zhangsan", say: ƒ}
</script>

事件绑定方法

事件绑定时,this指向当前事件所绑定的对象

<button>点我</button>
<script type="text/javascript">
	var btn = document.querySelector('button');
	btn.onclick = function() {
	    console.log(this)   //button按钮
	}
</script>

定时器函数

定时器里的函数是回调函数,所有回调函数的this都指向Window

<script type="text/javascript">
	setTimeout(function() {
		console.log(this) //Window {window: Window, self: Window, document: document, name: "", location: Location, …}
	}, 1000)
</script>

立即执行函数(自调用函数)

严格模式下this是undefined,正常模式是Window

<script type="text/javascript">
	(function(){
	    'use strict'
	    console.log(this)   //undefined
	})()
</script>

改变函数内部的指向

1. call方法
  • call()方法调用一个对象
  • 简单理解为调用函数的方式,但是它可以改变函数的 this 指向
  • 应用场景: 经常做继承
<script type="text/javascript">
	var f1 = {
		name: 'zhangsan'
	}
	function fn(a, b) {
	      console.log(this);
	      console.log(a+b)
	};
	fn()	// 此时this的指向是window
	fn.call(f1,1,2) //此时的this指向的是对象f1,参数使用逗号隔开
	
	// call 第一个可以调用函数 第二个可以改变函数内的this 指向
	// call 的主要作用可以实现继承
	function Father(name, age, sex) {
	    this.name = name;
	    this.age = age;
	    this.sex = sex;
	}
	
	function Son(name, age, sex) {
	    Father.call(this, name, age, sex);
	}
	var son = new Son('张三', 23, '男');
	console.log(son);
</script>

在这里插入图片描述

2. apply方法
  • apply() 方法调用一个函数
  • 简单理解为调用函数的方式,但是它可以改变函数的 this 指向
  • 应用场景: 经常跟数组有关系
<script type="text/javascript">
	var f1 = {
		name: 'andy'
	}
	 function fn(a, b) {
	      console.log(this);
	      console.log(a+b)
	};
	fn()// 此时的this指向的是window
	fn.apply(f1,[1,2])//此时的this指向的是对象o,参数使用数组传递
	// 1. 也是调用函数 第二个可以改变函数内部的this指向
	// 2. 但是他的参数必须是数组(伪数组)
	// 3. apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值 
	// Math.max();
	var arr = [1, 66, 3, 99, 4];
	var arr1 = ['red', 'pink'];
	// var max = Math.max.apply(null, arr);//不需要改变this指向,写null
	var max = Math.max.apply(Math, arr);//但是写null不太合适,写max的调用者Math最好,最大
	var min = Math.min.apply(Math, arr);//但是写null不太合适,写max的调用者Math最好,最小
	console.log(max, min);
</script>

在这里插入图片描述

3. bind方法
  • bind() 方法不会调用函数,但是能改变函数内部this 指向,返回的是原函数改变this之后产生的新函数
  • 如果只是想改变 this 指向,并且不想调用这个函数的时候,可以使用bind
  • 应用场景:不调用函数,但是还想改变this指向
 <script type="text/javascript">
	var f1 = {
		name: 'andy'
	};

	function fn(a, b) {
		console.log(this);
		console.log(a + b);
	};
	var f = fn.bind(f1, 1, 2); //此处的f是bind返回的新函数
	f(); //调用新函数  this指向的是对象f1 参数使用逗号隔开
</script>

在这里插入图片描述

4. call、apply、bind三者异同
  • 共同点 : 都可以改变this指向
  • 不同点:
    • call 和 apply 会调用函数, 并且改变函数内部this指向.
    • call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递
    • bind 不会调用函数, 可以改变函数内部this指向.
  • 应用场景
    1. call 经常做继承.
    2. apply经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
    3. bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向

严格模式

ES5的严格模式是采用具有限制性javaScript变体的一种方式,即在严格的条件下运行。IE10以上支持,旧版本会被忽略。 特点:

  • 消除了JavaScript语法的一些不合理、不严谨之处
  • 消除代码运行中的不安全之处,保证运行安全
  • 提高编译器效率,增加运行速度。
  • 禁用了在ECMScript的未来版本中可能会定义的一些语法,如一些保留字不能做变量名(class、enum、export、extends、import、super)
  • 严格模式可以应用到整个脚本或者个别函数中 为脚本开启严格模式 需要在所有的js语句之前写
'use strict';
//下面的js代码会按照严格模式执行

有的js是基本模式,有些是严格模式的情况,可以将真个脚本文件放在一个立即执行的匿名函数中,这样独立创建一个作用域,不影响其他js脚本文件

<script type="text/javascript">
	(function() {
		"use stroct";

	})()
</script>

为函数开启严格模式 在函数内部第一行写’use strict’;

<script type="text/javascript">
	function fun(){
	  'use strict';
	//函数内部下面的代码按照严格模式执行
	}
</script>

严格模式的要求

  • 正常模式中,如果一个变量没有声名就赋值,默认是全局变量。严格模式禁止这种用法,变量必须先声名,才能使用。
  • 严禁删除已经声名的变量。
<script type="text/javascript">
	'use strict';
	var x = 10;
	delete x; //会报错
	console.log(x)
</script>
  • 严格模式下this 指向问题 普通模式下this指向window对象,严格模式下全局作用域中函数中的this是undefined。 严格模式下,构造函数不加new调用,会报错,加new调用,this指向的还是创建的实例 定时器中的this指向还是window 事件、对象还是指向调用者
  • 函数中不能有重名的参数
  • 现版本的JavaScript引入“块级作用域”ES6中已经引入,所以严格模式不允许在非函数的代码块中sh声明函数。 如 if {} for(){} 严格模式不允许用8进制

量必须先声名,才能使用。

  • 严禁删除已经声名的变量。
<script type="text/javascript">
	'use strict';
	var x = 10;
	delete x; //会报错
	console.log(x)
</script>
  • 严格模式下this 指向问题 普通模式下this指向window对象,严格模式下全局作用域中函数中的this是undefined。 严格模式下,构造函数不加new调用,会报错,加new调用,this指向的还是创建的实例 定时器中的this指向还是window 事件、对象还是指向调用者
  • 函数中不能有重名的参数
  • 现版本的JavaScript引入“块级作用域”ES6中已经引入,所以严格模式不允许在非函数的代码块中sh声明函数。 如 if {} for(){} 严格模式不允许用8进制