Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(四)javascript高级程序设计: 引用类型 #4

Open
3 tasks done
Quickeryi opened this issue Jun 6, 2017 · 6 comments
Open
3 tasks done

(四)javascript高级程序设计: 引用类型 #4

Quickeryi opened this issue Jun 6, 2017 · 6 comments

Comments

@Quickeryi
Copy link
Owner

Quickeryi commented Jun 6, 2017

本文旨在记录js引用类型的一些核心概念

引用在手,天下我有 👍

  • Array
var arr = [1,]; // length = 1

// 类型判断
arr instanceof Array;
Array.isArray(arr);
// 分析:由于第一种方式其实是通过原型链判断(即:arr.__proto__ === Array.prototype),所以当数组在一个执行环境中创建,而传入另一个环境中时,此时原型链就不一致了(两个不同的全局环境,构造函数不一样),所以判断就会失败。
// 方法二则不会有这种问题

// toString, toLocaleString
var person1 = {
     toString() { return 1; },
     toLocaleString() { return 2; }
};
var person2 = {
     toString() { return 3; },
     toLocaleString() { return 4; }
};
var person = [person1, person2];
person.toString(); // 调用每一项的toString, 然后‘,’分割
person.toLocaleString();// 调用每一项的toLocaleString, 然后‘,’分割

// 当数组的某一项为undefined时,进行拼接操作时(调用join、toString等方法)会处理为‘’
var arr = [1, , 2];
arr.join(); // '1,,2'

// sort(): 实际上先调用数组每一项的toString()方法,再比较字符串的编码值
 
## 数组方法
1)不会改变原素组的方法:concat、slice、forEach、every、filter、map、some
2)会改变原素组的方法:pop、push、shift、unshift、sort、reverse、splice

## slice(start, end)
1)技巧: arr.slice(0, -1) // 返回除最后一项的数组
2)说明:start >= end 返回空数组

#splice(start, count [,x,x])
1)始终返回一个数组,包含删除的元素
2)有三种作用:删除、替换、插入

# 位置方法:内部使用全等匹配
1)indexOf(findItem[, start])
2)lastIndexOf(findItem[, start])

#迭代方法:都不会改变原数组,且都会忽略空档元素
1)forEach:return undefined
   - 遍历空档值会跳过,值为undefined或者“”,不会跳过
   - forEach遍历的范围在第一次调用 callback 前就会确定,所以会存在以下特性:1)调用forEach 后添加到数组中的项不会被 callback 访问到;2)如果数组在迭代时被修改了,则其他元素会被跳过
2)map:return a new array
   - callback必须要有返回值,否则返回的数组内部的元素都为undefined
   - 返回的数组大小等于原数组
3)filter:return a new array
   -  与map类型
4)some && every:return true or false
5)reduce:return 函数累计处理的结果
   - 不提供 initialValue ,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。提供 initialValue ,从索引0开始
   - 如果数组为空并且没有提供initialValue, 会抛出TypeError
   - 如果数组仅有一个元素(无论位置如何)并且没有提供initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行
# 构造函数:实际上只接受毫秒数作为参数
1)不传参数:先自动获取当前日期的毫秒数,然后调用构造函数
2)一个字符串参数:等价于先调用Date.parse(字符串),然后获取返回的毫秒数,再调用构造函数
3)两个以上参数:等价于先调用Date.UTC(年份,月份 [,....] ),然后获取返回的毫秒数,再调用构造函数
4)Date.parse && Date.UTC传入的参数无效时,返回NaN,Date.UTC只传入一个参数时,返回1970/1/1零点的毫秒数

#获取当前时间毫秒数:+new Date() || Date.now()

#valueOf():返回时间的毫秒数 (等价于 getTime()

#setXXX相关方法都会改变原Date实例对象,且当值大于最大值时,往前进一位,例如: d.setMonth(13), 则增加年份
  • RegExp
#模式:
  - g:不会匹配到第一个字符串就停止
  - i
  - m:多行

#构造函数:RegExp("pattren", "flags") => 注意此时pattren中的所有元字符需要双重转义
eg:/\w\\hello\\123/gi ==> new RegExp("\\w\\\\123", "gi")

#ps:每一个正则表达式,都是一个独立的实例,即:任意两个正则表达式不相等

# 实例属性
  - source:返回字面量形式正则表达式的pattren字符串
  - global、multiline、ignoreCase、lastIndex(表示开始搜索下一个匹配项的位置,从0开始,如果正则不是全局模式,则永远为0)

# exec():return array or null
   - return null:没有匹配项
   - return array:[0: 整个模式匹配字符串, 1: 捕获组1,  2: 捕获组2, xxx, input: exec()的参数, index: 匹配项在字符串中的位置]
   - demo
      var text = "cat, bat, sat, fat";
      var reg1 = /.at/; // 不是全局模式,在同一个字符串上多次调用,始终返回一样的结果
      var m1 = reg1.exec(text); // ["cat", index: 0, input: "cat, bat, sat, fat"]
      var m2 = reg1.exec(text); // ["cat", index: 0, input: "cat, bat, sat, fat"]

      var reg2 = /.at/g; // 即使设置全局模式,每次也只能匹配一项,需要反复调用,才能全部匹配完毕
      var m1 = reg2.exec(text); // ["cat", index: 0, input: "cat, bat, sat, fat"]
      var m2 = reg2.exec(text); // ["bat", index: 5, input: "cat, bat, sat, fat"]

# toString() 、toLocaleString():返回字面量的字符串
# valueOf():返回正则本身
# 静态属性:基于所执行的最近一次正则操作而变
   - RegExp.input:最近一次要匹配的字符串
   - RegExp.lastMatch:最近一次的匹配项
   - RegExp.lastParen:最近一次的匹配的捕获组
   - RegExp.leftContext:input中lastMatch的前部
   - RegExp.rightContext:input中lastMatch的后部

彻底领悟javascript中的exec与match方法:在全局模式下,match会返回所有匹配到项的数组,在不是全局模式下,match可以等价于exec
正则表达式中的贪婪和懒惰

@Quickeryi
Copy link
Owner Author

Quickeryi commented Jun 7, 2017

提供俩个数组扁平化操作方法

  • 使用reduce方法:
let arr = [1, [2], [3, [4, [5]]]];
let flatten = (arr) => {
     return arr.reduce(
         (prev, next) => {
             return prev.concat(Array.isArray(next) ? flatten(next) : next);
         },
         []
     );
}
flatten(arr); // [1, 2, 3, 4, 5]
  • 使用常规方法
let arr = [1, [2], [3, [4, [5]]]];
let flatten = (arr) => {
    let _arr_ = [];
    if (Array.isArray(arr)) {
        for (let i = 0, len = arr.length; i < len; i++) {
              _arr_ = _arr_.concat(flatten(arr[i]));
        }
    } else {
       _arr_.push(arr);
    }
    return _arr_;
}
flatten(arr); // [1, 2, 3, 4, 5]

@Quickeryi
Copy link
Owner Author

Quickeryi commented Jun 8, 2017

  • Function
# new Function("arg_name_1", "arg_name2", ..., "main_body")
1)不推荐上述方法:语义不明确;代码解析两次(第二次发生在解析传入的参数,类似于解析eval(''))
# 函数是一个对象(new Function(),所以函数名只是一个指针(此处有助于理解为啥木有重载功能)
# arguments.callee => 函数本身 , arguments.callee.caller => 调用该函数者
# 函数的属性和方法:
   - length:能够接收的命名参数个数
   - prototype
# apply(context, [args_array | arguments])
# bind() :返回指定作用域的函数实例

@Quickeryi
Copy link
Owner Author

  • 基本包装类型:Number、String、Boolean
var  s1 = 'this is a string';
s1.toUpperCase();
// 上述一段代码在后台实际的执行情况如下
var s1 = new String('this is a string');
s1.toUpperCase();
s1 = null;
// 基本包装类型的生命周期在代码执行方法后就销毁了

#Boolean
var b = new Boolean(false);
b && true; // true(此时是对b这个对象求值,所以为true)

var b = Boolean(false);
b && true; // false

# 基本包装类型不是对象实例
var num = Number(10);
num instanceof Number; // false

#String
 // 三个方法均不影响原数据
  - slice(start[, end])
  - substring(start[, end]):任一参数小于 0 或为 NaN => 0 任一参数大于 stringName.length,则被当作 stringName.length,注意:当第二个参数小于第一个参数时,会互换参数位置
  - substr(start[, length]) :length  0 或负值 => 0,则 substr 返回一个空字符串

@Quickeryi
Copy link
Owner Author

eval

  1. 通过eval执行的代码与执行调用eval的环境具有相同的作用域

  2. eval()中创建的任何变量和函数都不会在编译阶段被提升,只有在执行eval时才被解析

@Quickeryi Quickeryi changed the title javascript高级程序设计: 引用类型 (四)javascript高级程序设计: 引用类型 Jun 9, 2017
@Quickeryi
Copy link
Owner Author

数组去重

@Quickeryi
Copy link
Owner Author

提供一个实现连字符查找值的方法

// 输入: {a: {b: {c: 1}}}, ‘a.b.c’
// 输出:1

/**
 * 判断对象是否有 key
 */
let isEmpty = (obj) => {
    "use strict";
    for (let key in obj) {
      return false;
    }
    return true;
};

/**
 * 判断值是否为对象
 */
let isObject = (obj) => {
    "use strict";
    return toString.call(obj) === "[object Object]";
};

/**
 * 查找
 */
let find = (obj, key) => {
    "use strict";
    if (!isObject(obj) || isEmpty(obj) || !key) return void 0;
    let keys = key.split('.'),
        next = obj[keys[0]],
        result,
        next_key;
    keys.shift();
    next_key = keys.join('.');
    if (!next_key) {
        result = next;
    } else {
        result = find(next, next_key);
    }
    return result;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant