【慕课网】JavaScript中函数和this

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014465934/article/details/84674887

1.函数概述

JS中函数比较特殊,函数也是对象中的一种。常叫做函数对象。

所以JS函数可以像其它对象那样操作和传递,所以我们也常叫JS中的函数为函数对象。

函数的返回值依赖return,一般的函数调用:没有return就会默认在所有代码执行完返回一个undefined;
如果作为构造器,外部使用new去调用,这样没有return语句或者return后边是基本类型的话,那么会将this作为返回;反之如果return了一个对象的话,这个对象作为new构造器的返回值。

函数4调用方式(不同调用方式this指向不同):

  • 直接调用 foo();
  • 对象方法 o.method();
  • 构造器 new Foo();
  • call/apply/bind func.call(o);

JavaScript核心:this,arguments,构造函数,作用域,不同调用方式,不同创建方法,闭包,原型链prototype,原型继承_proto_

2.函数声明与表达式

定义函数的三种形式:

1.函数声明
function add(a,b){
	a = +a;
	b = +b;
	if(isNaN || isNaN(b)){
		return;
	}
	return a+b;
}

2.函数表达式
// function variable
var add = function(a,b){
	
};

//IEF(Immediately Executed Function) 立即执行函数表达式
(function(){

})();

//first-class function 作为返回值的函数表达式
return function(){

}

//NFE(Named Function Expression) 已命名的函数表达式
var add = function(a,b){

}

3.Function构造器
var func = new Function('a','b','console(a+b);')
func(1,2);   //3

var func = Function('a','b','console(a+b);')
func(1,2);   //3

在这里插入图片描述

附注:

一个完整语句,以function开头,例如:

// 这是函数声明
function foo() {

}

而用括号括起来的,或者前面有一元操作符的,都是函数表达式,例如:

// 函数表达式
(function foo() {

})

// 函数表达式
!function foo() {

}

// 函数表达式
+function foo() {

}

函数声明和函数表达式的区别:函数声明会被前置。

// 函数声明(函数声明被提前)
var num = add(1,2);
console.log(num);   // 3 

function add(a,b){
	return a+b;
}

// 函数表达式(变量add被提前,但是是undefined)
var num = add(1,2);
console.log(num);   //undefined is not a function

var add = function(a,b){
	return a+b;
}

在这里插入图片描述

Function构造器作用域和处理与一般函数有一定区别:

注:声明未定义和未声明的变量经过typeof都返回undefined

1.在函数构造器里面定义的变量是局部变量
Function('var localVal = "local";console.log(localVal);')();// 可以立即调用执行
console.log(typeof localVal);
// result:local,undefined (localVal仍为局部变量)

2.不能访问拿到外层函数的局部变量localVal(可以拿到全局对象,但是拿不到外层局部变量)
var globalVal = 'global';
(function(){
    var localVal = 'local';
    Function('console.log(typeof localVal,typeof globalVal);')();
})();
// result: undefined,string (local不可访问,全局变量global可以访问)

函数构造器(Constructor):

函数构造器就是可以用来构建生成新的函数或者对象的函数。

函数构造器也是一个普通函数,只不过在使用该函数构造生成新的函数或者对象的时候,该函数才会称为函数构造器。

构建的过程简单来说分两步:

1、创建一个空对象,并执行类似构造函数bind该空对象的过程。也就是把构造函数中的this指向新的空对象然后执行一遍,这个过程可以叫初始化。

2、把空对象的原型指向构造函数的原型,也就是构建原型链继承。

构建出的对象或者函数可以称为构造函数的一个实例,因为在完成初始化的过程就设定新对象的许多私有属性,而且该对象也继承了构建函数的原型链,及上面的共有属性。

3.this

this对象就是谁调用指向谁.

this在运行时才确定所指向的具体对象是谁。

1.当函数作为对象的方法调用时,this指向该对象。
2.当函数作为淡出函数调用时,this指向全局对象(严格模式时,为undefined)
3.构造函数中的this指向新创建的对象
4.嵌套函数中的this不会继承上层函数的this,如果需要,可以用一个变量保存上层函数的this。
再总结的简单点,如果在函数中使用了this,只有在该函数直接被某对象调用时,该this才指向该对象。

fn.call(o); //改变函数fn的作用域对象
fn.apply(o); //改变函数fn的作用域对象
fn.bind(o); //将函数fn的作用域绑定到对象o上

1.全局作用域下this(浏览器):

console.log(this.document === document); //true
console.log(this === window); //true

this.a = 37;
console.log(window.a); //37

2.一般函数的this(浏览器):

全局作用域下,this指向window,nodejs下是global;
严格模式下,this是undefined;

function f1(){
	return this;
}
f1() === window; //true,global object

function f2(){
	"use strict";
	return this;
}
f2() === undefined; //true

3.作为对象方法的函数this

this作为方法调用:作为对象方法调用 指向该对象

函数作为一个对象的属性的值,也常常叫作一个对象的方法。

// 函数作为一个对象的属性的值,也常常叫作一个对象的方法。
var o = {
	prop:37,
	f:function(){
		return this.prop;
	}
};
//调用对象的方法,该方法就是一个函数
console.log(o.f()); // 37 this指向对象o

var o = {prop:37};
function independent(){
	return this.prop;
}
// 函数赋给对象的属性
o.f = independent;
console.log(o.f()); // 37

4.对象原型链上的this

对象原型链上的this,不管是原型链上的还是本身,都可以拿到.

var o = {f:function(){return this.a + this.b; }};
var p = Object.create(o);

p.a = 1;
p.b = 4;

console.log(p.f());  // 5

get/set方法与this:指向get set方法所在的对象里面

function modulus(){
	return Math.sqrt(this.re*this.re + this.im*this.im);
}

var o = {
	re:1,
	im:-1,
	get phase(){
		return Math.atan2(this.im,this.re);
	}
}

Object.defineProperty(o,'modulus',{
	get:modulus,enumerable:true,configurable:true
)};

console.log(o.phase,o.modulus); // -0.78 1.4142

5.构造器中的this

构造器中的this,若没有return,this的指向会作为返回值.

函数的返回值依赖return,一般的函数调用:没有return就会默认在所有代码执行完返回一个undefined;
如果作为构造器,外部使用new去调用,这样没有return语句或者return后边是基本类型的话,那么会将this作为返回;反之如果return了一个对象的话,这个对象作为new构造器的返回值。

function MyClass(){
	this.a =37;
}
var o = new MyClass();
console.log(o.a); //37

function C2(){
	this.a = 37;
	return {a:38};
}
o = new C2();
console.log(o.a); // 38

6.call/apply方法与this

call/apply方法与this的应用场景及用法,call/apply可以传入一个对象作为函数作用域里的this.

function add(c,d){
    return this.a + this.b + c + d;
}
var o = {a: 1,b: 3};
 
add.call(o, 5,7);//1+3+5+7 = 16
 
add.apply(o, [10,20]);// 1+3+10+20 = 34
 
function bar(){
    console.log(Object.prototype.toString.call(this));
}
bar.call(7);// "[object Number]"

7.bind方法与this

bind将一个对象绑定为某对象里的(此处为函数)this后,被绑定的对象可以以特定的this,实现重复使用。

如这里的g()函数

function f(){
    return this.a;
}
var g = f.bind({a:"test"});
console.log(g());//test
 
var o = {a:37,f:f,g:g};
console.log(o.f(),o.g());//37,test,使用bind绑定this

4.arguments

this始终指向的是调用者,当函数作为构造器时,this指向的新创建的空对象,然后就会执行构造器的所有代码,碰见this.XXX就是为新建对象添加属性.如果构造器最后没有显示的使用return返回一个值,那么就会返回this即新建对象.

函数属性和arguments:

arguments是一个类数组对象,原型不是Array.prototype,所以它没有join等数组对象才有的方法。

可以通过索引访问arguments对象。

function foo(x,y,z){ //形参
    arguments.length;// 2 实参个数
    arguments[0];//1
    
    // 绑定关系
    arguments[0] = 10;
    x;//10  
    // 未传参数,失去绑定关系
    arguments[2] = 100;
    z;//undefined  
    
    arguments.callee === foo;//true
}
 
foo(1,2)
foo.length;// 3 形参个数
foo.name;// "foo" 函数名
arguments.length 实参个数

在这里插入图片描述

apply/call方法(浏览器)

function foo(x,y){
    console.log(x,y,this);
}
 
foo.call(100,2,,3);// 2,3,Number(100)不是对象的会转变成对象
foo.apply(true,[3,4]);// 3,4,Boolean
foo.apply(null);//undefined,undefined,window
foo.apply(undefined);//undefined,undefined,window

// 严格模式下
function foo(x,y){
   'use strict'; 
    console.log(x,y,this);
}
 
foo.apply(null);//undefined,undefined,null
foo.apply(undefined);//undefined,undefined,undefined

bind方法

this.x = 9;
var module = {
    x: 81,
    getX:function() {
        return this.x;
    }
}
 module.getX();//81对象.属性
  
 var getX = module.getX;
 getX();// 9 直接赋值给变量调用
  
 var boundGetX = getX.bind(module);
 改变函数运行是的this,绑定了module
  
 bondGetX();// 81

bind与currying

function add(a,b,c){
	return a+b+c;
}

var func = add.bind(undefined,100);
func(1,2); // 103

// 100+200+10 =310
var func2 = func.bind(undefined,200);
func2(10); // 310

在这里插入图片描述

bind与new

function foo(){
    this.b = 100;
    return this.a;
}
 
var func = foo.bind({a: 1});
 
func();//1
new func();// {b:100}

bind方法模拟:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u014465934/article/details/84674887