2. 函数的扩展

"Hello World, Hello Blog"

Posted by wudimingwo on December 15, 2018

返回指定长度的随机字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
      function Random (n) {
      	let max = 1;
      	for(let i = 0; i < n; i++) {
      	  max *= 10;
      	}
      	
      	return function () {
      		let str = '' + parseInt(Math.random() * max);

                下面这小段我就看不懂什么意思了
                count不是必然= 0 嘛?
                补0操作有可能执行嘛?
      		let count = n - str.length;
      		for(let i = 0; i < count; i++) {
      		  str += '0';
      		}
      		return str
      	}
      }
      
      let random8 = Random(8);
      
      console.log(random8());

#函数的默认值

第一种

1
2
3
4
      function fn (name) {
        var name = name || 'none';
      }
有缺陷 '',0,null,false 等值时达不到预期

第二种

1
2
3
      function fn (name) {
        var name = name === undefined ?  'none' : name;
      }

es6

1
2
3
4
5
6
7
      function fn (name = 'none') {
        // 绝对== undefined 时 才会走默认值
      }
babel 翻译
function fn() {
  var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'none';
}

情形1 ``` function Person (name, age = 18, weight) { this.name = name; this.age = age; this.weight = weight;

1
2
3
4
  }
  new Person('dd',undefined,63);
  想要触发默认值 必须要占位,而不能
  new Person('dd',,63);       ```

情形2 arguments 的表现

  1. 默认情况 ``` function num (num1) { console.log(num1, arguments[0]);//1,1 num1 = 3; console.log(num1, arguments[0]);//3,3 arguments[0] = 4; console.log(num1, arguments[0]);//4,4 } num(1);

默认情况下 arguments[0] 和 num1 互相绑定

1
> 2. 严格模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  function num (num1) {
      "use strict"
      console.log(num1, arguments[0]);//1,1
      num1 = 3;
      console.log(num1, arguments[0]);//3,1
      arguments[0] = 4;
      console.log(num1, arguments[0]);//3,4
  }
  num(1); 除了刚传入时保持一致, 互相并不绑定 ``` > 3. 设置默认值将触发严格模式 ```
  function num (num1 = 0) {
      console.log(num1, arguments[0]);//1,1
      num1 = 3;
      console.log(num1, arguments[0]);//3,1
      arguments[0] = 4;
      console.log(num1, arguments[0]);//3,4
  }
  num(1); ```

默认值可以是变量 ``` let obj2 = {}; obj2.num = 18; function num (obj = obj2) { console.log(obj.num);// 18 } num();

// 也就是说, 从某种角度来讲, 可以传两次参数? // 第二次不传, 就默认用第一次传的参数?

1
2
> 惰性求值?
1
2
3
4
5
6
7
8
9
  function getValue () {
  	console.log('hello');
  	return 6;
  }
  function add (m,n = getValue()) {
    return n + m;
  }
  console.log(add(1,1));
  console.log(add(1));

触发默认值时, 才会执行该函数. 有点类似回调?

1
2
3
4
> TDZ 暂时性死区
下面代码执行会报错嘛?
不会
1
2
3
4
5
  function add (m,n = m) {
    return n + m;
  }
  console.log(add(1,1));//2,2
  console.log(add(1));//2,2

相当于 let m = 1; let n = m;

1
2
下面代码执行会报错嘛?
会
1
2
3
4
5
  function add (m =n ,n) {
    return n + m;
  }
  console.log(add(1,1));//2,2
  console.log(add(undefined,1));// 报错 相当于  let m = n; let n = 1; ```

无命名参数和扩展运算符 参数不定时, 需要用arguments 来访问 箭头函数不支持arguments

作为形参使用,生成数组 ``` function add(arr, …arg) { console.log(arg); console.log(arguments); for(let i = 0; i < arg.length; i++) { arr[i] = arg[i] + 1; }

1
2
3
4
5
    return arg;
  }
  let arr = [];
  add(arr,1,2,3,4);
  console.log(arr);//[2,3,4,5]

babel 翻译 function add(arr) { for (var _len = arguments.length, arg = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { arg[_key - 1] = arguments[_key]; }

console.log(arg); console.log(arguments); for (var i = 0; i < arg.length; i++) { arr[i] = arg[i] + 1; }

return arg; }

可以看到 , …arg的处理 实际上用的是 arguments

1
2
3
4
5

> 每个函数只能有一个不定参数
下面代码是否会报错? 
会
1
2
3
4
5
6
7
8
9
10
11
12
  function add(arr,...arg,...arg1) {
    
  }
  add([],1,2,3,4); ``` > 不定参数不能有默认值 下面代码是否会报错?  会 ```
  function add(arr,...arg=[]) {
    
  }
  add([],1,2,3,4); ``` > 不定参数 必须放在最后面 下面代码是否会报错?  会 ```
  function add(first,...arg,last) {
    
  }
  add(1,2,3,4); ``` ----------------- 非形参使用时, 扒开数组. ```

function add(a,b,c) { console.log(a + b + c); return a + b + c } let arr = [1,2,3]; add(…arr);// 传参时使用

bable翻译

function add(a, b, c) { console.log(a + b + c); return a + b + c; } var arr = [1, 2, 3]; add.apply(undefined, arr);

看得出, 用的是apply

1
> 可用于数组合并
1
2
3
4
5
6
7
  let arr1 = [1,2,3];
  let arr2 = [4,5,6];
  let arr3 = arr1.concat(arr2);
  
  let arr4 = [...arr1,...arr2];
  
  console.log(arr3,arr4);

babel 翻译可知 用得也是concat

1
2
3
4
-----------------------------------------------------------------
# 箭头函数
> 基本形式
1
2
3
4
5
6
7
8
9
10
11
12
13
  () => {} ``` > 简写形式 ```
  let fn = name => name;
   对于小括号, 参数必须有且只有一个时,可省略
   对于 {} , 只有一条语句时, 可省略, 并且返回语句执行后的值 ``` 箭头函数中返回对象 ```
    let returnObj = (name) => ({name})  需要小括号包裹一下, 表明是对象. ``` 立即执行函数 ```
    let name = (name => name)('mike'); ``` > 箭头函数 > 1. 没有this > 2. 没有 arguments > 3. 没有super > 4. 没有prototype > 不能被 new 操作符运算 > call,apply,bind 也失去作用 ```
    let age = "mike";
    let fn =  () => {
      console.log(this == window);/ true
      console.log(this.age);/ undefined
    }
    fn();
    console.log(fn.prototype);/ undefined

babel翻译

var age = “mike”; var obj = { age: ‘18’ }; var fn = function fn() { console.log(undefined == window); console.log(undefined.age); // undefined }; var fn1 = fn.bind(obj); fn1();

// 可以看出, 所有this都换成了 undifend

1
2
3
4
5
6
7
8
9
10
11
12
> this 绑定分为四种 (权重一次递增)
> 1. 默认绑定(this 指向window)
> 2. 隐式绑定 ( this 指向 调用函数的对象)
> 3. 显示绑定 ( this 指向 call, apply, bind 绑定的对象)
> 4. new 绑定 ( this 指向 实例)

> 箭头函数中没有this
> 箭头函数中 this指向,离自己最近的非箭头函数作用域中的this
> (非箭头函数作用域是有this的, 而块级作用域{}是没有this的?)

下面代码输出结果是什么?
1
2
3
4
5
6
7
8
9
  var age = "peter";
  let obj = {
    age: 'mike',
    print: function() {
      let show = () => { console.log(this.age) };
      show();
    }
  }
  obj.print();// mike ```

应用, setTimeout

1
2
3
4
5
6
7
8
      var name = "mike";
      function show () {
      	setTimeout(() => {
      	  console.log(this.name);
      	},1000);
      }
      show();// mike
      show.call({name : "peter"});// peter

arguments与此类似,指向非箭头函数的arguments 这对使用setTimeout 就很友好感觉.

1
2
3
4
5
6
7
      function show () {
      	setTimeout(() => {
      	  console.log(arguments);//[1,2,3]
      	  console.log(arguments[0]);// 1
      	},1000);
      }
      show(1,2,3);//

阮一峰的es6, 函数扩展