Skip to content

函数进阶

基础知识

声明定义

对象字面量属性函数简写

javascript
let user = {
  name: null,
  getName: function (name) {
    return this.name;
  },
  //简写形式
  setName(value) {
    this.name = value;
  }
}
user.setName('love');
console.log(user.getName()); // love

使用let/const时不会压入 window

javascript
let hd = function() {
  console.log("love");
};
window.hd(); //window.hd is not a function

标准声明的函数优先级更高,解析器会优先提取函数并放在代码树顶端,所以标准声明函数位置不限制,所以下面的代码可以正常执行。

javascript
console.log(hd(3));
function hd(num) {
  return ++num;
};

标准声明优先级高于赋值声明

javascript
console.log(hd(3)); //4

function hd(num) {
  return ++num;
}

var hd = function() {
  return "5";
};

使用 let/const 有块作用域特性,所以使用以下方式也可以产生私有作用域

javascript
{
  let web = 'love';
}
console.log(web);//Uncaught ReferenceError: web is not defined

arguments

arguments 是函数获得到所有参数集合,下面是使用 arguments 求和的例子

javascript
function sum() {
  return [...arguments].reduce((total, num) => {
    return (total += num);
  }, 0);
}
console.log(sum(2, 3, 4, 2, 6)); //17

更建议使用展示语法

javascript
function sum(...args) {
 return args.reduce((a, b) => a + b);
}
console.log(sum(2, 3, 4, 2, 6)); //17

箭头函数

箭头函数是函数声明的简写形式,在使用递归调用、构造函数、事件处理器时不建议使用箭头函数。

标签函数

使用函数来解析标签字符串,第一个参数是字符串值的数组,其余的参数为标签变量。

javascript
function hd(str, ...values) {
  console.log(str); //["站点", "-", "", raw: Array(3)]
  console.log(values); //["love", "you"]
}
let name = 'love',url = 'you';
hd `站点${name}-${url}`;

this

his

调用函数时 this 会隐式传递给函数指函数调用时的关联对象,也称之为函数的上下文。

函数调用

全局环境下this就是 window 对象的引用

javascript
<script>
  console.log(this == window); //true
</script>

使用严格模式时在全局函数内thisundefined

对象字面量

  • 下例中的 hd 函数不属于对象方法所以指向window
  • show 属于对象方法执向 obj对象
js
let obj = {
    site: "love",
    show() {
        console.log(this.site) //love
        console.log(`this in show method: ${ this }`) //this in show method: [object Object]
        function hd() {
            console.log(typeof this.site) //undefined
            console.log(`this in hd function: ${ this }`) //this in hd function: [object Window]
        }
        hd()
    }
}
obj.show();

在方法中使用函数时有些函数可以改变 this 如forEach,当然也可以使用后面介绍的apply/call/bind

javascript
let Lesson = {
  site: "love",
  lists: ["js", "css", "mysql"],
  show() {
    return this.lists.map(function(title) {
      return `${this.site}-${title}`;
    }, this);
  }
};
console.log(Lesson.show());

也可以在父作用域中定义引用this的变量

javascript
let Lesson = {
    site: "love",
    lists: ["js", "css", "mysql"],
    show() {
      const self = this;
      return this.lists.map(function(title) {
        return `${self.site}-${title}`;
      });
    }
  };
  console.log(Lesson.show());

箭头函数

箭头函数没有this, 也可以理解为箭头函数中的this 会继承定义函数时的上下文,可以理解为和外层函数指向同一个 this。

  • 如果想使用函数定义时的上下文中的 this,那就使用箭头函数

下例中的匿名函数的执行环境为全局所以 this 指向 window

javascript
let name = 'loveagri'
let obj = {
    name: 'js',
    getName: function () {
        console.log(this.name) //js 
        return function () {
            return this.name
        }
    }
}
console.log(obj.getName()()) //loveagri

使用箭头函数时 this 指向上下文对象,匿名函数的一般使用event.target寻找上下文对象。

javascript
<body>
  <button desc="hdcms">button</button>
</body>
<script>
  let Dom = {
    site: "loveagri",
    bind() {
      const button = document.querySelector("button");
      button.addEventListener("click", event => {
        alert(this.site + event.target.innerHTML);
      });
    }
  };
  Dom.bind();
</script>

使用handleEvent绑定事件处理器时,this指向当前对象而不是 DOM 元素。

javascript
<body>
  <button desc="hdcms">button</button>
</body>
<script>
  let Dom = {
    site: "loveagri",
    handleEvent: function(event) {
      console.log(this);
    },
    bind() {
      const button = document.querySelector("button");
      button.addEventListener("click", this);
    }
  };
  Dom.bind();
</script>

apply/call/bind

改变 this 指针,也可以理解为对象借用方法

原理分析

构造函数中的this默认是一个空对象,然后构造函数处理后把这个空对象变得有值。

javascript
function User(name) {
  this.name = name;
}
let love = new User("love");

可以改变构造函数中的空对象,即让构造函数 this 指向到另一个对象。

javascript
function User(name) {
  this.name = name;
}

let love = {};
User.call(love, "love");
console.log(love.name); //love

apply/call

call 与 apply 用于显示的设置函数的上下文,两个方法作用一样都是将对象绑定到 this,只是在传递参数上有所不同。

  • apply 用数组传参
  • call 需要分别传参
  • 与 bind 不同 call/apply 会立即执行函数

bind

bind()是将函数绑定到某个对象,比如 a.bind(hd) 可以理解为将 a 函数绑定到 hd 对象上即 hd.a()。

  • 与 call/apply 不同 bind 不会立即执行
  • bind 是复制函数形为会返回新函数