二分搜索
二分搜索法,也称折半搜索,是一种在有序数组中查找特定元素的搜索算法。
有序的二分查找,返回-1或存在的数组下标。不使用递归实现
function binarySearch (target, arr) {
var start = 0;
var end = arr.length - 1;
while (start <= end) {
var mid = parseInt(start + (end - start) / 2); // 获取中间值取整
// 如果target等于中间值就直接返回
if (target === arr[mid]) {
return arr[mid];
}
// 如果target大于中间值就从右边开始寻找
else if (target > arr[mid]) {
start = mid + 1;
}
else {
end = mid - 1;
}
}
return -1;
}
无序的二分查找
// 无序的二分查找,返回-1或存在的数组下标。不使用递归实现
function binarySearch (target, arr) {
while (arr.length > 0) {
// 使用快速排序。以mid为中心划分大小,左边小,右边大。
var left = [];
var right = [];
// 选择第一个元素作为基准元素(基准元素可以为任意一个元素)
var pivot = arr[0];
// 由于取了第一个元素,所以从第二个元素开始循环
for (var i = 1; i < arr.length; i++) {
var item = arr[i];
// 大于基准的放右边,小于基准的放左边
item > pivot ? right.push(item) : left.push(item);
}
// 得到经过排序的新数组
if (target === pivot) {
return pivot;
}
else if (target > pivot) {
arr = right;
}
else {
arr = left;
}
}
return -1;
}
JavaScript instanceof 运算符代码
//L 表示左表达式,R 表示右表达式
function instance_of(L,R) {
var O = R.prototype; // 取R的显示原型
L = L.__proto__; // 取L的隐式原型
while(true) {
if (L === null) {
return false
}
// R.prototype === L.__proto__
if (O === L) { // 这里重点:当 O 严格等于 L 时,返回 true
return true;
}
L = L.__proto__;
}
}
on(注册一个事件)
Event.prototype.on = function (type, fun) {
let cbs = this._events[type];
cbs ? cbs.push(fun) : this._events[type] = [];
if(!cbs) {
this._events[type].push(fun)
}
}
这里为什么要将this._events设计为二维数组?因为事件可以是多个,但是事件名可能相同。
这个逻辑意图非常明显,根据type参数从this._events中获取是否存在。如果不存在,创建一个type为key的数组,并将事件句柄程序push到数组中。
off(注销一个事件)
Event.prototype.off = function (type, fun) {
let cbs = this._events[type];
// 事件队列中无事件
if (!cbs) {
return this;
}
// 删除所有的事件
if (!type && !fun) {
this._events = {};
return this;
}
// 只有事件名称时
if (type && !fun) {
this._events[type] = null;
return this;
}
// 删除某个事件队列中的某个事件
let cb;
let i = cbs.length;
while (i--) {
cb = cbs[i];
if (cb === fun || cb.fun === fun) {
cbs.splice(i, 1);
break;
}
}
};
虽然注销事件方法的逻辑可能相比下稍许多了些,但它的实现也非常简单,只要只存在事件组key名的情况,或者删除某个事件队列中的某个事件句柄程序即可
emit(触发一个事件)
Event.prototype.emit = function(type){
let cbs = this._events[type];
let args = tools.toArray(arguments,1);
if (cbs) {
let i = 0;
let j = cbs.length;
for(;i<j;i++){
let cb = cbs[i];
cb.apply(this,args);
}
}
}
这里通过事件名从this._events获取相应的事件句柄程序数组,然后将arguments转成数组,(这里考虑是可能会传入参数)如果事件句柄程序数组存在,进行循环,再将args参数apply给每一个取出来的事件句柄程序。
实现一个clon,对js中的5种主要数据类型镜像复制
function clone (obj) {
var o;
switch (typeof obj) {
case "undefined":
break;
case "string":
o = obj + "";
break;
case "number":
o = obj - 0;
break;
case "boolean":
o = obj;
break;
case "object": // object分为两种情况一种是对象 一种是数组
if (obj === null) {
o = null;
}
else {
if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
o = [];
for (var i = 0; i < obj.length; i++) {
o.push(clone(obj[i]));
}
}
else {
o = {};
for (var k in obj) {
o[k] = clone(obj[k]);
}
}
}
}
return o;
}
消除一个数组里面重复的元素
var arr1 = [1, 2, 2, 2, 3, 3, 3, 4, 5, 6];
var arr2 = [];
for (var i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) < 0) { // 如果要检索的字符串值没有出现
arr2.push(arr1[i]) // push进入数组
}
}
console.log(arr2); // [1, 2, 3, 4, 5, 6]
消除字符串前后空格
function trim (str) {
if (str && typeof str === 'string') {
return str.replace(/(^\s*)|(\s*$)/g, ''); //去除前后空白符
}
}
var str = ' ab ';
console.log(trim(str)); // ab
求一个字符串的字节长度
function GetBytes (str) {
var len = str.length;
var bytes = len;
for (var i = 0; i < len; i++) {
if (str.charCodeAt(i) > 255) {
bytes++;
}
}
return bytes
}
简单实现 Function.bind 函数
if (!function() {}.bind) {
Function.prototype.bind = function(context) {
var self = this;
var args = Array.prototype.slice.call(arguments);
return function() {
return self.apply(context, args.slice(1));
}
};
}
JavaScript中对一个对象进行深度clone
function cloneObject (obj) {
if (!obj || 'object' !== typeof obj) {
return obj
}
let clone = 'function' === typeof obj.pop ? [] : {};
let value;
// 遍历对象
for (i in obj) {
if (obj.hasOwnProperty(i)) {
value = obj[i];
if (value && 'object' !== value) {
clone[i] = cloneObject(value)
}
else {
clone[i] = value;
}
}
}
return clone
}
URL参数解析为一个对象
function parseQueryString (url) {
let param = {};
let arr = url.split('?');
if (arr.length <= 1) {
return;
}
arr = arr[1].split('&');
for (let i = 0; i < arr.length; i++) {
let data = arr[i].split('=');
param[data[0]] = data[1];
}
return param;
}
实现ECMAScript 5中的Object.getPrototypeOf() 函数
该方法返回的是指定对象的原型(内部[[Prototype]]属性的值) 如果参数不是一个对象类型就会抛出一个异常(ES5中参数会自动转换为对象)
function proto(obj) {
return !obj ? null : '__proto__' in obj ? obj.__proto__ : obj.constructor.prototype
}
实现Array.prototype.forEach?
Array.prototype.forEach = function (fn) {
for (let i=0;i<this.length;i++) {
fn(this[i],i,this)
}
}
兼容浏览器的获取指定元素(elem)的样式属性(name)的方法
function getStyle (ele, name) {
// 如果属性中存在style[]中就直接获取
if (ele.style[name]) {
return ele.style[name];
}
// IE方法
else if (ele.currentStyle) {
return ele.currentStyle[name]
}
// w3c方法
else if (document.defaultView && document.defaultView.getComputedStyle) {
name = name.replace(/(A-Z)/g,'$1').toLowerCase(); // W3C中为textAlign样式,转为text-align转换小写
let style = document.defaultView.getComputedStyle(ele);
return `${name}:${style.getPropertyValue(name)}`
}
}
函数记忆,判断是不是质数
function isPorimel (n) {
if (n <= 3) {
return true;
}
else {
for (let i = 2;i< Math.sqrt(n);i++) {
// 不能被其他自然数整除的数叫做质数
if (n % i === 0) {
return false;
}
}
return true
}
}
函数currying(柯里华)
let getN;
function add(n) {
getN = function (n) {
return n
}
return function (m) {
n += m;
argument.callee.toString = function() {
return n;
}
return argument.callee
}
}
递归
var emp={
work:function(){//3,2,1
var sum=0;//+3+2+1 +2+1 +1
for(vari=0; i<arguments.length&&arguments[0]>0;
i++){
sum+=arguments[i]
+arguments.callee(
--arguments[i]
);
}
return sum;
}
}
console.log(emp.work(3,2,1));//10
自定义Object.create()
Object.create = function (father) {
// 方法1
let obj = Object();
Object.setPrototypeOf(obj, father)
// 方法2
function Constructor(){}
Constructor.prototype = father
let obj = new Constructor();
return
}
深克隆原理
function clone(obj) {
if (typeof obj !== 'object') {
return obj;
}
let o = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {} // 区分数组和普通对象
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
o[key] = arguments.callee(obj[key]);
}
}
return o
}
every的实现原理
Array.prototype.every = function(fun){
for (let i=0;i<this.length;i++) {
if (this[i] !== undefined) {
let f = fun(this[i],i,this)
if (f === false) {
return false
}
}
}
return true
}
some的实现原理
Array.prototype.some = function (fun) {
for (let i = 0; i < this.length; i++) {
if (this[i] !== undefined) {
let r = fun(this[i], i, this);
if (r === true) {
return true
}
}
}
return false
};
map的实现原理
Array.prototype.map = function(fun){
// 创建一个数组
let newArray = []
// 遍历当前数组的元素
for (let i=0;i<this.length;i++) {
if (this[i] !== undefined) {
let r = fun(this[i],i,this)
newArray[i] = r
}
}
return newArray
}