12、Set、Map、Proxy、 Reflect、ts泛型、Iterator(遍历)、Generator(生成)、async、await、promise模拟、多态、原型链、create、defineProperty、parseFloat、jQuery之鼠标跟随、文档树效果、选项卡、全选、反选、四种宽获取、实例无new构建、业务逻辑

来源 http://caibaojian.com/es6
一、Set和Map
1、Set:ES6提供的新的数据结构,类似于数组,但是成员的值都是唯一的,没有重复的。
2、Map:ES6提供的新的数据结构,类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

二、Proxy(内部拦截)
1、Proxy实例(Proxy必须针对Proxy实例进行操作,否则Proxy不起作用)
(1)实例一
var obj = {};
var thisObj = new Proxy(obj, {
  get: function (target, key, receiver) {
    console.log(obj === target); //true
    if (key === 4) {
      return 5;
    }
    return 6;
  },
  set: function (target, key, value, receiver) {
    return Reflect.set(target, key, value, receiver);
  },
  has: function (target, key) {
    if (key[0] === "c") {
      return false;
    }
    return key in target;
  },
});
thisObj.count = 1;
console.log(thisObj.count);
console.log("count" in thisObj);
(2)实例二
var fn=function(){ };
var thisFn = new Proxy(fn,{
  construct:function(target,args){
    console.log(target===fn)//true
    return { value: args[0]*10 }//construct方法返回的必须是一个对象,否则会报错。
  }
});
console.log(new thisFn(1));
console.log(Reflect.construct(thisFn,[1]));
2、Proxy配置
(1get(target, propKey, receiver)
拦截对象属性的读取,比如proxy.starFunction 和 proxy['starFunction']。
如果propKey属性部署了读取函数,则读取函数的this绑定receiver(一个对象)。
(2set(target, propKey, value, receiver)
拦截对象属性的设置,比如proxy.starFunction = v或proxy['starFunction'] = v,返回一个布尔值。
(3)has(target, propKey)
拦截propKey in proxy的操作,以及对象的hasOwnProperty方法,返回一个布尔值。
(4)deleteProperty(target, propKey)
拦截delete proxy[propKey]的操作,返回一个布尔值。
(5)ownKeys(target)
拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy),返回一个数组。该方法返回对象所有自身的属性,而Object.keys()仅返回对象可遍历的属性。
(6)getOwnPropertyDescriptor(target, propKey)
拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
(7)defineProperty(target, propKey, propDesc)
拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
(8)preventExtensions(target)
拦截Object.preventExtensions(proxy),返回一个布尔值。
(9)getPrototypeOf(target)
拦截Object.getPrototypeOf(proxy),返回一个对象。
(10)isExtensible(target)
拦截Object.isExtensible(proxy),返回一个布尔值。
(11)setPrototypeOf(target, proto)
拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。
如果目标对象是函数,那么还有两种额外操作可以拦截。
(12)apply(target, object, args)
拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...) 。
(13)construct(target, args)
拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。

三、Reflect(外部操纵)
1、Reflect概述
Reflect对象与Proxy对象一样,也是ES6为了操作对象而提供的新API。Reflect对象的设计目的有这样几个。
(1) 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。
(2) 修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
(3) 让Object操作都变成函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。
(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
2、Reflect方法
(1)Reflect.get(target, name, receiver)
查找并返回target对象的name属性,如果没有该属性,则返回undefined。
如果name属性部署了读取函数,则读取函数的this绑定receiver。
var antzone = {
  webName: "蚂蚁部落",
  url:"www.softwhy.com",
  get age() { return this.myAge; }
}
console.log(Reflect.get(antzone, "age", { myAge: 4 }));
(2)Reflect.set(target, name, value, receiver)
设置target对象的name属性等于value。如果name属性设置了赋值函数,则赋值函数的this绑定receiver。
(3)Reflect.has(obj, name)
等同于name in obj。
(4)Reflect.deleteProperty(obj, name)
等同于delete obj[name]。
(5)Reflect.construct(target, args)
等同于new target(...args),这提供了一种不使用new,来调用构造函数的方法。
function func1(a, b, c) {
  this.sum = a + b + c;
}
const args = [1, 2, 3];
const object1 = new func1(...args);
const object2 = Reflect.construct(func1, args);
console.log(object2.sum);//expected output: 6
console.log(object1.sum);//expected output: 66)Reflect.getPrototypeOf(obj)
读取对象的__proto__属性,对应Object.getPrototypeOf(obj)。
(7)Reflect.setPrototypeOf(obj, newProto)
设置对象的__proto__属性,对应Object.setPrototypeOf(obj, newProto)。
(8)Reflect.apply(fun,thisArg,args)
等同于Function.prototype.apply.call(fun,thisArg,args)。一般来说,如果要绑定一个函数的this对象,可以这样写fn.apply(obj, args),但是如果函数定义了自己的apply方法,就只能写成Function.prototype.apply.call(fn, obj, args),采用Reflect对象可以简化这种操作。
console.log(Reflect.apply(Math.floor, undefined, [1.75]));// expected output: 1

四、ts泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
1、泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面,像函数声明一样.
function createArray<T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
createArray<string>(3, 'x'); // ['x', 'x', 'x']
2、泛型参数的默认类型
function createArray<T = string>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
3、泛型接口
interface CreateArrayFunc {
  <T>(length: number, value: T): Array<T>;
}
let createArray: CreateArrayFunc;
createArray = function<T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']
4、也可以把泛型参数提前到接口名上
interface CreateArrayFunc<T> {
  (length: number, value: T): Array<T>;
}
let createArray: CreateArrayFunc<any>;
createArray = function<T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']
5、泛型类
TypeScript的核心原则之一是对值进行类型检查。
在TypeScript里,接口的作用就是为这些类型命名和为代码定义契约。
https://www.tslang.cn/docs/handbook/interfaces.html
class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
6、泛型约束
interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}
7、对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量
我们定义一个接口来描述约束条件。 创建一个包含 .length属性的接口,使用这个接口和extends关键字来实现约束。
 
五、Iterator(遍历器)
//以下遍历器(迭代器)模拟代码
function createIterator(items) {
  var i = 0;
  return {
      next: function() {
          var done = (i >= items.length);
          var value = done ? undefined : items[i++] ;
          return {
              done: done,
              value: value
          };
      }
  };
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
JavaScript原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6又添加了Map和Set。这样四种数据结构只要部署了Iterator接口,就是”可遍历的“(iterable)。ES6规定,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
const obj = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};
上面代码中,对象obj是可遍历的(iterable),因为具有Symbol.iterator属性。

六、Generator 函数(生成器)
1、Generator函数有两个特征
(1)function关键字与函数名之间有一个星号;
(2)函数体内部使用yield(即“产出”)语句,定义不同的内部状态。
2、调用Generator函数后,该函数并不执行,返回的是一个指向内部状态的指针对象,也就是遍历器对象(Iterator Object)。
3、调用遍历器对象的next方法,使得指针移向下一个状态。
4、也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield语句(或return语句)为止。
5、换言之,Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行。
6、示例1
function* starFunction(one) {
  console.log(one);
  var two = 2 * (yield one + 1); //6,7
  console.log("1111111111111111111111111111111");
  console.log(two);
  var three = yield 2 * two; //4,8
  console.log("2222222222222222222222222222222");
  console.log(three);
  var four = yield 2 * three; //2,4
  console.log("3333333333333333333333333333333");
  console.log(four);
  console.log(one, two, three, four);
  console.log("4444444444444444444444444444444");
  return one + two + three + four;
}
var useFunction = starFunction(6);
console.log(useFunction.next());
console.log(useFunction.next(2));
console.log(useFunction.next(2));
console.log(useFunction.next(2));
next第1次执行,返回“第1个yield语句的计算结果”;
next第2次执行,返回“第2个yield语句的计算结果”,传入的参数取代“第1个yield语句的计算结果”;
next第3次执行,返回“第3个yield语句的计算结果,传入的参数取代“第2个yield语句的计算结果””;
next第n次执行时,如果没有第n个yield语句,那就一直执行到return,如果没有return,就返回undefined。
7、示例2   
来源:http://www.ruanyifeng.com/blog/2015/04/generator.html
Fetch模块返回的是一个Promise对象,因此要用then方法调用下一个next方法。
var fetch = require('node-fetch');
function* generatorFn(){
  var urlA = 'https://api.github.com/users/githubA';
  var urlB = 'https://api.github.com/users/githubB';
  yield fetch(urlA);
  yield fetch(urlB);
}
var generatorOne = generatorFn();
var result = generatorOne.next();
result.value.then(function(data){
  return data.json();
}).then(function(data){
  generatorOne.next(data);
});
8、如果想要第一次调用next方法时,就能够输入值,可以在Generator函数外面再包一层。如下
function wrapper(generatorFunction) {
  return function (num) {
    let generatorObject = generatorFunction(num);
    generatorObject.next();
    return generatorObject;
  };
}
const wrapped = wrapper(function* starFunction(a) {
  console.log(a);
  var b = 2 * (yield a + 1); //6,7
  console.log("1111111111111111111111111111111");
  console.log(b);
  var c = yield 2 * b; //4,8
  console.log("2222222222222222222222222222222");
  console.log(c);
  var d = yield 2 * c; //2,4
  console.log("3333333333333333333333333333333");
  console.log(d);
  console.log(a, b, c, d);
  console.log("4444444444444444444444444444444");
  return a + b + c + d;
});
var b = wrapped(6);
console.log(b.next(2));
console.log(b.next(2));
console.log(b.next(2));

七、async(then)函数及其内部的await(promise)指令
(1)async函数可以包含await指令,该指令会暂停原异步函数的执行,并等待右侧Promise返回结果;
(2)若 Promise 正常处理,其回调resolve函数的参数作为 await 表达式的值;
示例一:
function thisPromise(x) {
  return new Promise(function (resolve) {
    //此处把x(加工后)作为参数向后台发送请求
    setTimeout(function () {
      //此处获得后台返回结果并加工为x+50,通过resolve暴露出去
      resolve(x + 50);
    }, 500);
  });
}
async function thisAdd(x) { //var thisAdd = async function(x) {
  var a = await thisPromise(20);
  var b = await thisPromise(30);
  //此处可以加工a,b
  return x + a + b; //这个结果作为参数传给后面的then参数
}
thisAdd(10).then(function (total) {
  console.log(total); //1 秒后出打印结果
});
  
八、promise内部机制模拟和校验
//1、promise模拟
function custPromise(callback) {
  this.value = null;
  this.status = "pending";
  this.cbArray = [];
  callback(this.resolve.bind(this));
}
custPromise.prototype.then = function (success) {
  var that = this;
  if (this.status == "pending") {//success为异步函数时
    return new custPromise(function (resolve) {//同步将then参数放在实例参数里
      that.cbArray.push(function () {//push参数就是下面的callbackIn
        var result = success(that.value);//success来自哪个实例,that.value就来自哪个实例
        if (result instanceof custPromise) {
          result.then(resolve);
        } else {
          resolve(result); //上面result.then(resolve)执行时,产生了这里的resolve
        }
      });
    });
  }
  if (this.status == "resolve") {//success为同步函数时
    return new custPromise(function (resolve) {
      var result = success(that.value);
      if (result instanceof custPromise) {
        result.then(resolve);
      } else {
        resolve(result);
      }
    });
  }
};
custPromise.prototype.resolve = function (value) {
  this.value = value;
  this.status = "resolve";
  if (this.cbArray.length > 0) {
    this.cbArray.forEach(function (callbackIn) {
      callbackIn(); //callbackIn就是上面的push参数
    });
  }
};
//2、promise验证
//第1个上实例的自身参数为异步时,它的then参数为异步或同步的情况
//第1个上实例的自身参数为同步时,它的then参数为异步或同步的情况
new custPromise(function (resolve) {
  setTimeout(function () {
    resolve(1);
  }, 2000);
})
.then(function (value) {
  return new custPromise(function (resolve) {
    setTimeout(function () {
      resolve(value * 2);
    }, 1000);
  });
})
.then(function (value) {
  return new custPromise(function (resolve) {
    setTimeout(function () {
      resolve(value * 2);
    }, 1000);
  });
})
.then(function (value) {
  return new custPromise(function (resolve) {
    resolve(value * 2);
  });
})
.then(function (value) {
  return new custPromise(function (resolve) {
    resolve(value * 2);
  });
})
.then(function (value) {
  return value * 2;
})
.then(function (value) {
  console.log(value)
});

九、多态
同一操作作用于不同的对象上面,可以产生不同的执行结果。比如你说“叫”,鸭子听了会发出“嘎嘎声”,鸡听了会发出“咯咯声”。
1、非多态代码示例
var makeSound = function(animal) {
  if(animal instanceof Duck) {
    console.log('嘎嘎嘎');
  } else if (animal instanceof Chicken) {
    console.log('咯咯咯');
  }
}
var Duck = function(){}
var Chiken = function() {};
makeSound(new Chicken());
makeSound(new Duck());
2、多态的代码示例
var makeSound = function(animal) {
  animal.sound();
}
var Duck = function(){}
Duck.prototype.sound = function() {
  console.log('嘎嘎嘎')
}
var Chiken = function() {};
Chiken.prototype.sound = function() {
  console.log('咯咯咯')
}
makeSound(new Chicken());
makeSound(new Duck());
十、原型链
(1)函数类或对象类或普通函数_的原型(直接找原型,简单)
(2)函数类或对象类或普通函数或普通对象_所在类的原型(先找类再找原型,复杂)
(3)函数类或对象类或普通函数或普通对象_所在类的原型_之所在类的原型...(先找类再找原型,复杂)
var obj = {}
function fn(){}
1、函数类或对象类或普通函数的原型
(1)Object.prototype={};
(2)Function.prototype={};
(3)fn.prototype = {};
2、函数类或对象类或普通函数或普通对象_所在类的原型
(1)Function.__proto__ === Function.prototype
(2)Object.__proto__ === Function.prototype
(3)fn.__proto__ === Function.prototype;
(4)obj.__proto__ === Object.prototype;
3、函数类或对象类或普通函数或普通对象_所在类的原型_之所在类的原型...
(1)Function.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototype
(2)Object.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototype
(3)Function.__proto__.__proto__.__proto__ === Function.prototype.__proto__.__proto__ === Object.prototype.__proto__ === null4)Object.__proto__.__proto__.__proto__ === Function.prototype.__proto__.__proto__ === Object.prototype.__proto__ === null
4、new出来的对象
function AAA() {}
AAA.prototype.bbb = function () {};
var aaa = new AAA();
console.log(aaa.__proto__ === AAA.prototype);
console.log(aaa.__proto__.__proto__ === Object.prototype);
//https://www.jianshu.com/p/686b61c4a43d
附:原型链继承
Drag.prototype.__proto__ = EventEmitter.prototype;//这是更安全的继承方法,一般在Node里都是采用这种方式实现继承。IE不支持
Drag.prototype = new EventEmitter;//相对这种方式来说,上边的写法更安全

十一、Object.create(proto[, propertiesObject])
1、参数
(1)proto:新创建对象的原型对象
(2)propertiesObject:新创建对象的(可)枚举属性
2、返回值
(1)一个新对象,带着指定的原型对象和属性
3、实例
var myProto={proto:1};
var youProto={
  enumer:{
    enumerable: true,
    value: "custom"
  }
};
var thisProto=Object.create(myProto,youProto)
console.log(thisProto)
console.log(thisProto.enumer)
console.log(thisProto.__proto__===myProto)

十二、Object.defineProperty() 
1、语法:Object.defineProperty(myObject, prop, descriptor)
2、参数:
(1)myObject要定义或修改的属性所在的对象
(2)prop要定义或修改的属性的名称
(3)descriptor要定义或修改的属性的描述符,包含A、configurable,B、enumerable,C、数据描述符(2项)或存取描述符(2项)
3、返回值:myObject
4、作用:定义或者修改myObject的属性
5、configurable,默认为false。为true时,prop可删,描述符可改
6、enumerable,默认为false。为true时,prop可枚举
7、数据描述符:
(1)value,属性值,可以是数值、对象、函数等,默认为 undefined。
(2)writable,默认为false。为true时,prop可重写。
8、存取描述符:
(1get,属性的getter函数,当访问prop时,会调用此函数,该函数的返回值被用作属性值,默认为undefined。
(2set,属性的setter函数,当属性值被修改时,会调用此函数,该函数接受1个参数,默认为undefined。
示例一
var myObj = { thisValue: 5 };
Object.defineProperty(myObj, "key", {
  configurable: false,
  enumerable: false,
  value: function () {
    console.log(this);
    return this.key+1;
  },
  writable: true,
  //value: "myValue",
  //writable: false,
});
myObj.key = 5;
console.log(myObj.key);
示例二
var myObj = { thisValue: 5 };
Object.defineProperty(myObj, "key", {
  configurable: false,
  enumerable: false,
  get: function () {
    console.log(this);
    return key+2;
  },
  set: function (value) {
    console.log(this);
    key = value + 1;
  },
});
myObj.key = 5;
console.log(myObj.key);
附、vue响应式相关代码
function def(obj, key, val, enumerable) {
  Object.defineProperty(obj, key, {
    configurable: true,
    enumerable: !!enumerable,
    value: val,
    writable: true,
  });
}
Object.defineProperty(obj, key, {
  configurable: true,
  enumerable: true,
  get: function reactiveGetter() {
    var value = getter ? getter.call(obj) : val;
    return value;
  },
  set: function reactiveSetter(newVal) {
    var value = getter ? getter.call(obj) : val;
    dep.notify();
  },
});

十三、与parseFloat()相关
原文地址:https://yq.aliyun.com/ziliao/92498?spm=5176.8246799.blogcont.20.cUDmIE
1、Number()
(1)如果是Boolean值,true和false值将分别被转换为1和0。
(2)如果是数字值,只是简单的传入和返回。
(3)如果是null值,返回0。
(4)如果是undefined,返回NaN。
(5)如果是字符串:
A、如果字符串中只包含数字时,将其转换为十进制数值,忽略前导0
B、如果字符串中包含有效浮点格式,如“1.1”,将其转换为对应的浮点数字,忽略前导0
C、如果字符串中包含有效的十六进制格式,如“0xf”,将其转换为相同大小的十进制数值
D、如果字符串为空,将其转换为0
E、如果字符串中包含除上述格式之外的字符,则将其转换为NaN
(6)如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再依照前面的规则转换返回的字符串值。
例: 
var num1 = Number("Hello world");       //NaN
var num2 = Number("");            //0
var num3 = Number("0000011");        //11
2、parseInt()
(1)处理整数的时候parseInt()更常用。parseInt()函数在转换字符串时,会忽略字符串前面的空格,知道找到第一个非空格字符。
(2)如果第一个字符不是数字或者负号,parseInt() 就会返回NaN,同样的,用parseInt() 转换空字符串也会返回NaN。
(3)如果第一个字符是数字字符,parseInt() 会继续解析第二个字符,直到解析完所有后续字符串或者遇到了一个非数字字符。
(4)parseInt()方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。
(5)基是由parseInt()方法的第二个参数指定的,所以要解析十六进制的值,当然,对二进制、八进制,甚至十进制(默认模式),都可以这样调用parseInt()方法。
例:
var num1 = parseInt("AF",16);           //175
var num2 = parseInt("AF");            //NaN
var num3 = parseInt("10",2);           //2  (按照二进制解析)
var num4 = parseInt("sdasdad");         //NaN
3、parseFloat()
(1)与parseInt() 函数类似,parseFloat() 也是从第一个字符(位置0)开始解析每一个字符。也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。
(2)也就是说,字符串中第一个小数点是有效的,而第二个小数点就是无效的了,它后面的字符串将被忽略。
(3)parseFloat() 只解析十进制,因此它没有第二个参数指定基数的用法
(4)如果字符串中包含的是一个可解析为正数的数(没有小数点,或者小数点后都是零),parseFloat() 会返回整数。
例:
var num1 = parseFloat("123AF");           //123
var num2 = parseFloat("0xA");            //0
var num3 = parseFloat("22.5");            //22.5
var num4 = parseFloat("22.3.56");         //22.3
var num5 = parseFloat("0908.5");          //908.5
parseInt() 和parseFloat() 的区别在于:
parseFloat() 所解析的字符串中第一个小数点是有效的,而parseInt() 遇到小数点会停止解析,因为小数点并不是有效的数字字符。
parseFloat() 始终会忽略前导的零,十六进制格式的字符串始终会被转换成0,而parseInt() 第二个参数可以设置基数,按照这个基数的进制来转换。
4、customParseInt:字符串类型的数字转换成数字类型的数字、数字类型的数字和字符串类型的非数字保持原样
function customParseInt(num) {
  var tempNum = parseInt(num);
  if (typeof tempNum === 'number' && !isNaN(tempNum)) {
    return tempNum;
  }
  return num;
};
console.log(customParseInt(1))
console.log(customParseInt("1"))
console.log(customParseInt("闪烁"))
4、整型范围
(1)有负号整型范围
Int8:[-128:127]
Int16:[-32768:32767]
Int32:[-2147483648:2147483647]
Int64:[-9223372036854775808:9223372036854775807]
(2)无负号整型范围 
UInt8:[0:255]
UInt16:[0:65535]
UInt32:[0:4294967295]
UInt64:[0:18446744073709551615]
十四、jQuery实现鼠标跟随
所谓鼠标跟随,一般就是指鼠标移到哪张图片上,那该张图片的放大图片就会出现,并且放大图片会随着鼠标在该张图片上移动而移动。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    img {
      border: none;
    }
    .box {
       660px;
      position: relative;
    }
    .box .mark {
      position: absolute;
       400px;
      height: 300px;
      display: none;
    }
    .box .mark img {
       100%;
    }
    .box img {
       150px;
      float: left;
      margin: 5px;
    }  
  </style>
</head>
<body>
<div class="box" id="box">
  <img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=e95708d565639d99576ae7cb00729334" 
    realImg="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=5328802dc943fc046e109f70359add0a" alt=""/>
  <img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=9e5459a7c0098c27adf4bdd73889caa9" 
    realImg="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=846f4d1987765dc4cfd5a06fcdd2dcc1" alt=""/>
  <img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=3cd1c8e301007f0c94850139ac79cb5a" 
    realImg="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=747bf3f7092ebd2b0bf9fcd27e28bbe5" alt=""/>
  <img src="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=f391169b2cf678aa6fd253cf40d9821d" 
    realImg="http://www.qdfuns.com/misc.php?mod=attach&genre=editor&aid=fec8d2f20fad1f28d540337a831e89d0" alt=""/>
  <div id="mark" class="mark"><img src="" alt=""/></div>
</div>
<script src="http://s0.kuaizhan.com/res/skin/js/lib/jquery-2.0.3.min.js"></script>
<script>
  //1.鼠标移入哪张图片的时候,让他对应的大图显示;
  //2.当鼠标在img中移动的时候,大图跟着走;
  var $box=$('.box');
  var $aImg=$box.children('img');
  var $mark=$('.mark');
  var $offset=$box.offset();
  $aImg.mouseover(function(){
    //当鼠标移入每张图片的时候,让mark显示,并且,让mark里面的img标签,src属性值为当前这个图片的realImg属性上拿到的值;
    $mark.show().find('img').attr('src',$(this).attr('realImg'));
  });
  $aImg.mousemove(function(e){
    //拿鼠标的x坐标,减去$box距离body的left位置;
    var left= e.clientX-$offset.left+10;
    var top= e.clientY-$offset.top+10;
    $mark.css({left:left,top:top})
  });
  $aImg.mouseout(function(){
    $mark.hide();
  })
</script>
</body>
</html>

十五、jQuery实现文档树效果
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    * {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .box {
       250px;
      height: auto;
      padding: 20px;
      background: lightgrey;
      margin: 0 auto;
    }
    .box li {
      line-height: 30px;
      /*注意:height没有被设置,可以根据实际需要自动调整*/
      position: relative;
    }
    .box li em {
      position: absolute;
      left: 0;
      top: 7px;
       16px;
      height: 16px;
      background-image: url("");
      background-size: 100%;
      cursor: pointer;
    }
    .box li em.open {
      background-image: url("");
      background-size: 100%;
    }
    .box li span {
      padding-left: 20px;
      /*因为span前面的em已经绝对定位,脱离文档流了,所以span的左边界直达 li*/
    }
    .box ul {
      display: none;
    }
    .two {
      margin-left: 20px;
    }
    .three {
      margin-left: 40px;
    }
    .four {
      margin-left: 40px;
    }
    /*ul.box下的li显示,其中有折叠的li加em;
    ul.box下的ul隐藏,其内部的li是没法显示的*/
  </style>
</head>
<body>
<ul class="box">
  <li><em></em><span>第一级第一个</span>
    <ul class="two">
      <li><span>第二级第一个</span></li>
      <li><em></em><span>第二级第二个</span>
        <ul class="three">
          <li><em></em><span>第三级第一个</span>
            <ul class="four">
              <li><span>第四级第一个</span></li>
              <li><span>第四级第二个</span></li>
            </ul>
          </li>
          <li><span>第三级第二个</span></li>
        </ul>
      </li>
      <li><em></em><span>第二级第三个</span>
        <ul class="three">
          <li><span>第三级第一个</span></li>
          <li><span>第三级第二个</span></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><em></em><span>第一级第一个</span>
    <ul class="two">
      <li><span>第二级第一个</span></li>
      <li><em></em><span>第二级第二个</span>
        <ul class="three">
          <li><em></em><span>第三级第一个</span>
            <ul class="four">
              <li><span>第四级第一个</span></li>
              <li><span>第四级第二个</span></li>
            </ul>
          </li>
          <li><span>第三级第二个</span></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
<script src="http://s0.kuaizhan.com/res/skin/js/lib/jquery-2.0.3.min.js"></script>
<script>
  /*思路:
    * 1.让前面有em的span加上小手效果;
    * 2.点击span or em的时候,看他父容器下是否有ul,如果有,让其显示,否则,隐藏
    * */
  var $box=$('.box');
  var $aSpan=$box.find('span');
  //1.让前面有em的span加上小手效果;
  $aSpan.each(function(index,item){
    //if($(item).prev().length){ $(item).css('cursor','pointer');};思路1:
    $(item).prev('em').next('span').css('cursor','pointer'); //思路2:
  });
  //2.点击span or em的时候,看他父容器下是否有ul,如果有,让其显示,否则,隐藏
  $box.click(function(e){
    //当点击的事件源是em or span的时候,我们看其父级下是否有ul
    // 如果有:展开让其闭合,闭合就让其展开;
    if(e.target.tagName.toLowerCase()=='em' || e.target.tagName.toLowerCase()=='span'){
      var $parent=$(e.target).parent();
      var $ul=$parent.children('ul');
      if($ul){
        if($ul.css('display')=='block'){//展开,让其闭合
          //当闭合的时候,让当前容器下,所有的em都移除open,所有的ul都隐藏;
          $parent.find('ul').hide();
          $parent.find('em').removeClass('open');
        }else{ //闭合让其展开
          $ul.show();
          $parent.children('em').addClass('open');

        }
      }
    }
  })
</script>
</body>
</html>

十六、jQuery方法扩展(选项卡)
在jQuery上扩展方法,通过点击实现选项卡的切换。本实例在jQuery的类上扩展,即$.extend({chooseCard:函数}),通过$.chooseCard('#box')调用;有别于$.fn.extend({chooseCard:函数})扩展,通过$().chooseCard('#box')调用。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    .box {
       312px;
      border: 2px red solid;
      margin: 0 auto;
    }
    ul {
      overflow: hidden;
    }
    li {
      list-style: none;
      background: red;
      float: left;
       100px;
      height: 30px;
      line-height: 30px;
      text-align: center;
      border: 2px solid orange;
    }
    li.on {
      background: green;
    }
    .box div {
      background: green;
      display: none;
       312px;
      height: 200px;
      font-size: 30px;
      border-top: none;
    }
    .box div.on {
      display: block;
    }
  </style>
</head>
<body>
<div class="box" id="box">
    <ul>
      <li class="">中国</li>
      <li>日本</li>
      <li>韩国</li>
    </ul>
    <div class="on">中国是老大</div>
    <div>日本是老二</div>
    <div>韩国是老三</div>
</div>
<script src="http://s0.kuaizhan.com/res/skin/js/lib/jquery-2.0.3.min.js"></script>
<script>
  (function ($) {
    $.extend({
      chooseCard: function (idStr) {
        var $box = $(idStr);
        var $li = $box.find("li");
        console.log($li);
        var $aDiv = $box.find("div");
        $li.click(function () {
          $(this)
            .css({ height: "32px", "border-bottom": "none" })
            .siblings("li")
            .css({ height: "30px", "border-bottom": "2px solid orange" });
          $(this).addClass("on").siblings("li").removeClass("on");
          $aDiv
            .eq($(this).index())
            .addClass("on")
            .siblings("div")
            .removeClass("on");
        });
      },
    });
  })(jQuery);
</script>
<script>
  $(function(){
    $.chooseCard('#box');
  })
</script>
</body>
</html>

十七、复选框全选、反选(<input type='checkbox'/>)
(1)获取复选框状态:$("#allSelect").prop("checked")
(2)改变复选框状态:$("#allSelect").prop("checked",false)
(3)翻转复选框状态:item.checked = !item.checked;
(4)判断复选框是否被选中:if ($(this).is(':checked'))
(5)找到所有被选中的复选框:myDiv.find("input:checked");
(6)获取所有复选框:$("#single input:checkbox")或$("#single input[type=checkbox]");
(7)获取所有被选中的复选框:$("#single input:checkbox:checked")或$("#single input[type=checkbox]:checked");

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.9.0/jquery.js"></script>
</head>
<body>
<span>全选</span><input type="checkbox" id="allSelect"><br>
<span>反选</span><input type="checkbox" id="reverseSelect">
<div id="single">
  <input type="checkbox">
  <input type="checkbox">
  <input type="checkbox">
  <input type="checkbox">
</div>
</body>
</html>
<script>
  $("#allSelect").click(function () {
    $("#single")
      .children()
      .each(function (index, item) {
        item.checked = $("#allSelect").prop("checked");
      });
    $("#reverseSelect").prop("checked", false);
  });
  $("#reverseSelect").click(function () {
    $("#single")
      .children()
      .each(function (index, item) {
        item.checked = !item.checked;
      });
    $("#reverseSelect").prop("checked", true);
    singleInput();
  });
  $("#single")
    .children()
    .click(function (index, item) {
      $("#reverseSelect").prop("checked", false);
      singleInput();
    });
  function singleInput() {
    if (
      $("#single input:checkbox:checked").length ==
      $("#single input:checkbox").length
    ) {
      $("#allSelect").prop("checked", true);
    } else {
      $("#allSelect").prop("checked", false);
    }
  }
</script>

十八、jQuery中的width()、innerWidth()、outerWidth()的区别总结
(1)width():其宽度范围是所匹配元素的宽度width;
(2)innerWidth():其宽度范围是所匹配元素的宽度width+padding;
(3)outerWidth():其宽度范围是所匹配元素的宽度width+padding+border;
(4)outerWidth(true)其宽度范围是所匹配元素的宽度width+padding+border+margin;

十九、jQuery实例无new构建
(function(window) {
  var jQuery = function(selector, context) {
    return new jQuery.prototype.init(selector, context, rootjQuery);
  }, 
  jQuery.prototype = {
    init: function( elem, options, prop, end, easing, unit ) {
      this.elem = elem;
      this.prop = prop;
      this.easing = easing || jQuery.easing._default;
      this.options = options;
      this.start = this.now = this.cur();
      this.end = end;
      this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
    },
  }
  jQuery.prototype.init.prototype = jQuery.prototype;
})(window);

二十、业务逻辑
(1)不同的项目有不同的功能,不同的功能需要不同的实现,实现这些核心功能的代码就叫业务逻辑。
(2)实现核心功能的代码就叫业务逻辑。
 
原文地址:https://www.cnblogs.com/gushixianqiancheng/p/11929936.html