js进阶知识—函数

2020-8-10~8-16 函数部分遗漏的知识将在今后学习之中慢慢总结。

函数:

1-1声明式(Function Declaration):
function fn() {
         console.log('我是函数声明式');
     }
    //  fn();两种调用方法
    fn.call();
1-2表达式(Function Expression):
var fn = function(aru) {
        console.log(aru);
    };
	//aru是形参
    fn('我是函数表达式');

fn是变量名,不是函数名,里面存的是一个函数。所以也称为匿名函数。函数的表达式需要在语句的结尾加上分号,表示语句结束。

1-3 new Function()定义:

var fn = new Function(‘参数1’, ‘参数2’, …, ‘函数体’) 所有函数都是Function的实例(对象)。

var sum = new Function('a', 'b', 'console.log(a + b)');
sum(1, 2);
//所有函数都是Function的实例(对象)
//函数也属于对象
console.log(sum instanceof object);

//等同于:
function sum(a, b) {
    console.log(a + b);
}
sum(1, 2);

可以传递任意数量的参数给Function构造函数,只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体。Function里面的参数必须是字符串的格式。这种声明函数的方式非常不直观,较少使用。

2-1立即执行函数IIFE:
(function(a, b){     //匿名函数自调用
    console.log(a + b);
})(1, 2);//函数定义完,立即被调用,立即执行函数往往只会执行一次
2-2回调函数:

定义后没有调用,但函数自己执行了。

①dom事件回调函数:

<button>点击</button>
var btn = document.querySelector('button');
btn.onclick = function() {
	alert(this.innerHTML);
}

②定时器回调函数:

setTimeout(function(){
	alert('2秒钟到了');
}, 2000)
2-3箭头函数:

箭头函数里面没有this, arguments不能使用

var sum = function(x, y) {
	return x + y;
};   //匿名函数
var sum2 = (x, y) => {
	return x + y;
}; //箭头函数,由于函数体只有一行代码,可以简写如下
var sum2 = (x, y) => x + y; //如果只有一个参数,小括号也可以省略  var sum2 = x => {}

<button>点击按钮变成红色</button> 
const btn = document.querySelector('button');
btn.addeventListener('click', function() {
	this.style.backgroundColor = 'red';  
});  //此时点击按钮后,样式会变成红色,但改为如下所示的箭头函数后会显示backgroundColor未定义
<button>点击按钮变成红色</button> 
const btn = document.querySelector('button');
btn.addeventListener('click', () => {
    console.log(this === window);     //true
	//this.style.backgroundColor = 'red';  将function()改为箭头函数后,为btn设置样式会显     //示未定义的报错,原因就是箭头函数里面没有this
});  //
3-1变量:

对于顶层函数来说,函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。全局变量在网页关闭后删除。在函数内部定义的变量(使用var),称为局部变量(local variable),外部无法读取。当函数执行完毕,本作用域内的局部变量会销毁。

3-2const

声明常量,常量就是值(内存地址)不能变化的量。

①不允许重复使用 ②不属于顶层对象window ③不存在变量提升 ④暂时性死区 ⑤块级作用域

const arr = [100, 200];  //复杂数据类型,数据内容可以更改,但数据值本身不可更改
arr[0] = 'a';
arr[1] = 'b';
console.log(arr);  //['a', 'b'] 并没有更改arr常量在内存中的存储地址
arr = ['a', 'b']; //,而此种赋值操作则更改了arr在内存中的存储地址
const PI = 3.14;
PI = 100; //报错,因为常量声明后,值(简单数据类型)不可更改
3-3作用域(scope):

指的是变量存在的范围。在 ES5 的规范中,JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。ES6 又新增了块级作用域。

③块级作用域:一对{}就产生了块级作用域,在块级作用域中声明的变量只能在{}里访问,如es6中的let声明的变量和const声明的常量。

if(true) {
	const str = 'es6';
	let a = 10;    	 //此时const和let声明的变量只在{}里面有用
}
console.log(str);
console.log(a);   //会报错,如果将const 和 let改为var,则不会报错。
3-4暂时性死区:

比如在es6中,如下面代码所示的{}作用域中在num被声明之前就使用了num,会报错。

var num = 10;
if(true) {
	console.log(num);
	const num = 20; //或者let num = 20;
} //会报错,因为由const和let在{}里面声明的num和整个块级作用域绑在一起了,在声明之前就使用会报错,    //而且不能访问{}外面的同名变量num
3-5闭包(closure)(GC):

指有权访问另一个函数作用域中变量的函数。(简单理解就是,一个作用域可以访问另外一个函数内部的局部变量)//闭包的主要作用:延伸了变量的作用范围。

function fn() {
	var num = 10;
    function fun() {
        console.log(num);
        //此时fun访问了fn作用域中的局部变量num
    }
    fun();
}
fn();

可以使以上代码中的内部函数fun在执行前,从外部函数返回。加一个return简化成以下代码

//fn外面的作用域也可以访问fn内部的局部变量。
function fn() {
    var num = 10;
    return function() {
        console.log(num);
    }
}
var f = fn();//此时在fn函数的外面也可以访问fn作用域里面的局部变量,局部变量也没有被销毁,因为在
f(); 		//fn函数的外面始终有一个f在等待着调用fn。
//类似于var f = function(){console.log(num);}
3-6 this:

①普通函数的this指向window

function fn() {
    console.log('普通函数的this' + this);
}
fn();
//但是在严格模式下全局作用域中函数中的this是undefined

②对象的方法:this指向的是该方法所属对象o

var o = {
 sayHi: function() {
 console,log('对象的方法this:' + this);
 }
}
o.sayHi();

③构造函数this指向实例对象tom,原型对象里面的this指向的也是实例对象tom

function Person() {};
Person.prototype.sing = function{};
var tom = new Person();

④绑定事件函数的this指向的是绑定事件对象btn

<button>点击</button>
var btn = document.querySelector('button');
btn.onclick = function() {
	console.log('绑定事件函数的this:' + this);
};

⑤定时器函数的this指向的是window

//应该在setTimeout前面加上window
setTimeout(function(){
	console.log('定时器的this:' + this)}1000);

⑥立即执行函数的this指向window

function(){
	console.log('立即执行函数的this' + this)})();
3-7改变函数内部this指向:

常用的有call(),apply(),bind()三种方法。

①call()方法调用一个对象。简单理解为调用函数的方式,同时它也可以改变函数的this指向。fun.call(thisArg, arg1, arg2…)

var o = {
	name: 'tom'
};
function fn(a, b) {
    console,log(this);
    console.log(a + b);
};
//call()里面不传参数o时this指向的是window,传了之后指向对象o,同时给定参数1,2进行计算
fn.call(o, 1, 2)//tom 3

call()的主要作用可以实现继承

function Father(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
function Son(name, age, sex) {
    //调用Father里面的属性,首先调用函数,然后修改this使其指向Son,同时传递参数
    Father.call(this, name, age, sex);
}
var son = new Son('tom', 18, '男');
console.log(son);

②apply()方法调用一个函数,简单理解为调用函数的方式,它可以改变函数的this指向。

fun.apply(thisArg, [argsArray]) thisArg:在fun函数运行时指定的this值, argsArray:传递的值,必须包含在数组里面。

var o = {
	name: 'tom'
};
function fn(arr) {
    console.log(this);
    console.log(arr);
};
fn.apply(o, ['参数必须是数组形式(伪数组)']);

**apply()的主要应用是:**与数组有关系,如可以利用apply借助于数学内置对象求最大值,最小值。

var arr = [1, 9, 3, 6, 5];
var max = Math.max.apply(Math, arr);
//指向函数max的调用者Math
var min = Math.min.apply(Math, arr);
console.log(max, min);//9

③bind()方法不会调用函数,但是能改变函数内部this指向。

fun.bind(thisArg, arg1, arg2, …) thisArg:在fun函数运行时指定的this值,arg1,arg2:传递的其他参数,返回由指定的this值和初始化参数改造的原函数拷贝

var o = {
    name: 'tom'
};
function fn(a, b) {
    console.log(this);
    console.log(a + b);
};
//不会调用原来的函数
var f = fn.bind(o, 1, 2);
//返回的是改变this之后产生的新函数
f();//返回o对象 和 3

有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向,此时用bind的方法最合适。

创建一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启
<button>点击</button>
var btn = document.querySelector('button');
btn.onclick = function() {
	this.disabled = true;//这个this指向的是btn
    setTimeout(function(){
        //不能直接写this.disabled = false;因为此时的this指向的是window。解决方法:
        //可以在setTimeout上面声明一个var that = this;然后在setTimeout里面将this改为
        //that.disabled,但是这种办法很麻烦要新开辟一块内存空间存放that。
        //最佳方法是在定时器函数的外面绑定bind()方法
        this.disabled = false;//加了bind方法之后this指向btn(点击对象)
    }.bind(this), 3000);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值