10.9 this
函数的this关键字在JavaScript中的表现略有不同。在严格模式下和非严格模式下略有差异
在绝大多数情况下,函数的调用方式决定了this的值(运行时绑定),this不能在执行期间被赋值 并且在每次函数被调用时this的值也会不同。ES5引入了bind方法来设置函数的this值
无论是否在严格模式下,全局环境中this都指向全局对象
console.log(this===window); //返回true
a=37;
console.log(window.a); //返回37
this.b="MDN";
console.log(window.b); //返回 MDN
console.log(b); //"MDN"
在函数内部,this的值取决于函数被调用的方式
function f1(){
return this;
}
conosole.log(f1()===window); //返回true
然而,在严格模式下,如果进入执行环境时没有设置this的值,this会保持为undefined
function f2(){
"use strict";
return this
}
console.log(f2()===undefined); //返回true
bind方法
function f(){
return this.a;
}
var g=f.bind(a:"JackMa");
console.log(g());
var h=g.bind(a:"MarkJie");
console.log(h()); //返回 JackMa,bind只能绑定一次
var o={a:37,f:f,g:g,h:h};
console.log(o.a,o.f(),o.g(),o.h()); //返回37 37 JackMa JackMa
当函数作为对象里的方法被调用时,this被设置为调用该函数的对象。 下面的例子中,当o.f()被调用时,函数内部的this将绑定在o对象上
var o={
prop:37,
f:function(){
return this.prop;
}
}
console.log(o.f()); //返回 37
原型链中的this
对于在对象原型链上某处定义的方法,同样的概念也适用。如果该方法存在一个对象的原型链上,那么this指向的是调用这个方法的对象,就像该方法在该对象上一样。
var o={
f:function(){
return this.a+this.b;
}
}
var p=Object.create(o);
p.a=1;
p.b=5;
console.log(p.f()); //返回 5
var s=new Object(o);
s.a=20;
s.b=5;
console.log(s.f()); //返回 25,这里的this.a是s.a
Sample1 哪个对象调用的方法,方法中的this就指向那个对象
window.color="red";
let o={
color:"blue";
}
let s={
color:"black";
}
function sayColor(){
return this.color;
}
console.log(this.sayColor()); //返回 red this指向window
o.sayColor=sayColor;
console.log(o.sayColor()); //返回 blue this指向o
s.sayColor=sayColor;
console.log(s.sayColor()); //返回 black this指向s
10.10 函数属性和方法
前面提到过,ECMAScript中的函数是对象,因此有属性和方法。每个函数都有两个属性length和prototype,其中,length属性保存函数定义的命名参数个数。
prototype属性
prototype属性是ECMAScript中最有趣的部分。prototype是保存引用类型所有实例方法的地方。 意味着,toString()、valueOf()等方法实际上都保存在prototype上
function还有两个函数,一个是apply()和call()这两个方法都会指定this值来调用函数。
sample\apply()函数
let nums=[1,3,5,7,9];
function sum(num1,num2){
return num1+num2;
}
function callSum1(num1,num2){
return sum.apply(this,arguments); //传入 arguments对象
}
function callSum2(num1,num2){
return sum.apply(this,[num1,num2]);
}
console.log(callSum1(10,10)); //返回 20
console.log(callSum2(100,200)); //返回 300
function plu(num){
let ret=0;
for(let=0;i<num.length;i++){
ret+=num[i];
}
return ret;
}
nums.push(55);
function callSum3(num){
return plu.apply(this,arguments);
}
function callSum4(num){
return plu.apply(this,[num]);
}
console.log(callSum3(nums)); //返回 80
console.log(callSum4(nums)); //返回 80
console.log(Math.max.apply(null,nums)); //返回 55
console.log(Math.min.apply(null,nums)); //返回 1
console.log(plu.apply(null,[nums])); //返回 80
注意,apply(this,[nums]) [nums]为一个类数组的参数,可以是arguments可以是数组
apply()和call()真正强大的地方并不是给函数传参。而是控制函数调用上下文,即函数体内this值得能力
Sample控制函数的参数调用
window.color="red";
let p={
color:"pink",
}
let b={
color:'black'
}
function sayColor(){
return this.color;
}
sayColor(); //返回red
sayColor.call(this); //返回 red
sayColor.call(window); //返回 red
sayColor.call(p); //返回 pink
sayColor.call(b); //返回 black
bind方法
bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被指定为bind()的第一个参数,而其余参数作为新函数的参数供调用。
const test={
name:"JackMa",
getName:function(){
return this.name;
}
}
const notGetX=test.getName;
console.log(notGetX()); //返回 undefined
const GetX=notGetX.bind(test);
console.log(GetX()); //返回42
bind()最简单的用法是创建一个函数,无论怎样调用,这个函数都有同样的this值。JavaScript新手经常犯的错误是将一个方法从对象中拿出来,然后再调用。期望方法中的this还是原来的对象。如果不做特殊处理,则会丢失
10.11 函数表达式
函数表达式包括函数声明和函数表达式 MDN:函数在JS中是头等公民,它和其它对象一样具有属性和方法,简而言之函数是Function对象的实例
sample 在FireFox中打开
let fun=function(x,y){
return x+y;
}
console.log(fun.constructor); //fun的constructor指向fun的构造函数,返回的是Function
形参和实参
函数定义
语法:
function FUNC([parms,[parms]]){statements};
FUNC 函数名,parms参数,statements组成函数体的声明语句