基于原生JS封装数组原型上的sort方法
基于原生JS封装数组原型上的sort方法
最近学习了数组的原型上内置方法的封装,加强了用原生JS封装方法的能力,也进一步理解数组方法封装的过程,实现的功能。虽然没有深入底层,了解源码。以下解法都是基于个人理解用纯原生JS实现的功能。如有不对的地方,可以评论告诉我哟
首先,我们先来看一下sort方法的作用、参数、以及方法的返回值,原有数组是否发生改变
sort方法主要用于数组的排序
参数分为两种:
- 一种:传的参数是函数、 (排序主要看函数的返回值)
- 另一种:传的不是函数、或者不传(只要传的不是函数就对原来排序过程不产生影响)
方法的返回值是原来数组排序后的数组
原来数组发生改变,是排序后的数组
其次,我们来看一下sort方法要处理的各种情况之间的比较
情况1:
无参实现对字符串数组的排序
情况2:
无参实现对number类型的数组进行排序
情况3:
无参实现对字符串、number等混合类型的数组的排序
情况4:
带参实现对number类型的数值数据排序
情况5:
带参sort()对简单对象List的自定义属性排序
情况6:
带参实现对字符串、number混合类型的数组的排序
sort方法对参数的处理:
情况1:如果参数不是函数,则不影响原来排序过程
情况2:如果参数是函数,则根据回调函数中的返回值进行排序。如果返回值大于0,则交换位置;如果返回值小于0,则不交换位置
如果返回值不是一个数字,则不交换位置
基于以上情况的讨论,sort方法实现的核心原理如下:
核心原理:不带参(以及带的参数不是函数)的情况下:默认升序排列
不带参的情况下,直接转字符串,逐个比较ASCII码的值
只要有一个是对象{}就不交换
带参数为函数的情况下:
根据函数的返回值进行比较;如果函数返回值大于0;则交换位置
实现代码如下:
Array.prototype.mySort = function(fn){
if(Object.prototype.toString.call(fn)==='[object Function]'){
//如果传进来参数的是函数
for(var i = 0;i<this.length-1;i++){
//遍历数组,将前后两项作为实参传给fn
if(fn.call(this,this[i],this[i+1])>0){
//如果fn执行之后的返回值大于0.就调用swap方法交换位置
var a = this[i],b=this[i+1];
this[i] = swap(a,b).a;
this[i+1] = swap(a,b).b;
//交换之后,如果当前项不是第一项,则当前项(索引为i的项)继续跟前面的项进行比较
if(i>0){
for(var j = i-1;j>=0;j--){
if(fn.call(this,this[j],this[j+1])>0){
var a = this[j],b=this[j+1];
this[j] = swap(a,b).a;
this[j+1] = swap(a,b).b;
}
}
}
}
}
}else{
//如果不是函数,则按正常排序
//遍历数组,将前后两项进行比较
for(var i = 0;i<this.length-1;i++){
var cur = this[i];//当前项
var next = this[i+1];//下一项
if(comASCII(cur,next)){
//当返回true的时候交换,并且交换完成之后,当前项继续往前比较
this[i] = swap(cur,next).a;
this[i+1] = swap(cur,next).b;
//当前项继续向前比较
if(i>0){
for(var k = i-1;k>=0;k--){
var cur = this[k];
var next = this[k+1];
if(comASCII(cur,next)){
this[k] = swap(cur,next).a;
this[k+1] = swap(cur,next).b;
}
}
}
}
}
}
//封装一个交换位置的函数
function swap(a,b){
return {
a:b,
b:a
}
}
//如果不传参的情况下比较ASCII码
function comASCII(cur,next){
//全部转换为字符串、逐项比较ASCII码
cur = cur.toString();
next = next.toString();
//取长度最大值
var len = cur.length>next.length?next.length:cur.length;
//当前后两项都不是不是{}类型的数据时,进行比较
if(cur!=='[object Object]'&&next!=='[object Object]'){
for(var j = 0;j<len;j++){
if(!isNaN(cur.charCodeAt(j))&&!isNaN(next.charCodeAt(j))){
//如果二者的ASCII码都是有效数字
if(cur.charCodeAt(j)>next.charCodeAt(j)){
//如果前一项比后一项当前的ASCII码大,则返回true,交换位置
return true;
}else if(cur.charCodeAt(j)==next.charCodeAt(j)){
//如果相等直接进入下一轮循环
continue;
}else{
//前项比后项小,直接返回false
return false;
}
}
}
if(!isNaN(cur.charCodeAt(len))&&isNaN(next.charCodeAt(len))&&(cur.charCodeAt(len-1)==next.charCodeAt(len-1))){
//比较完之后,如果前一项ASCII还是有效数字,说明前项比后项大,交换
return true;
}
}
//如果上述条件不满足,则不交换
return false;
}
//返回当前数组
return this;
};
实验结果
无参(参数非函数)对纯数字数组的排序
带参对纯数字数组的排序(升序)
带参对纯数字数组的排序(降序)
无参(参数非函数)对纯字母字符串数组的排序
带参(参数是函数)对纯字母字符串数组的排序(升序)
带参(参数是函数)对纯字母字符串数组的排序(降序)
无参(参数非函数)对纯字母字符串、数字字母组合字符串、纯数字字符串组合的排序
带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(升序)
带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(降序)
无参(参数非函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果
带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(升序)
带参(参数是函数)对纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的组合排序结果(降序)
无参(参数非函数)对数组、纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的排序
带参(参数是函数)对数组、纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的排序(升序)
带参(参数是函数)对数组、纯字母字符串、纯数字、数字字母字符串、纯数字字符串等的排序(降序)
带参(参数是函数)对纯数组的排序(升序)
带参(参数是函数)对纯数组的排序(降序)
带参(参数是函数)对纯对象的排序(升序)
带参(参数是函数)对纯对象的排序(降序)
基于原生JS封装数组原型上的sort方法的更多相关文章
- 用jQuery基于原生js封装的轮播
我发现轮播在很多网站里面都用到过,一个绚丽的轮播可以为网页增色不少,最近闲来无事,也用原生js封装了一个轮播,可能不像网上的插件那么炫,但是也有用心去做.主要用了闭包的思想.需要传递的参数有:图片地址 ...
- 基于原生js的图片延迟加载
当页面图片比较多的时候,我们通常会做一个延迟加载,避免页面打开时一下子的请求数太多,加载过慢影响用户体验. 如果项目用了jquery框架,则可以直接用 jquery.lazyload.可在jquery ...
- 基于原生js的返回顶部组件,兼容主流浏览器
基于原生js的返回顶部插件,兼容IE8及以上.FF.chrome等主流浏览器. js文件中封装了getScrollTop()和changeScrollTop()函数分别用于获取滚动条滚动的高度和修改滚 ...
- 原生JS封装创建多级菜单函数
手写一个使用原生JS封装的多级菜单的函数,满足以下几点需求. 子类层级不确定,可根据数据自动生成多级菜单. 操作便捷,只需传入一个HTML标签. 缺点: 需要满足特定的数据结构 废话不多说,展示代码. ...
- 用原生js封装轮播图
原生js封装轮播图 对于初学js的同学来说,轮播图还是一个难点,尤其是原生js封装轮播图代码,下面是我之前做的一个轮播图项目中封装好的一些代码,有需要的同学可以看一下,有什么不懂的可以看注释,注释看不 ...
- 使用原生JS封装一个动画函数
最近一直在忙项目,很少有时间回顾之前的知识,今天刚好要做一个轮播,因为对兼容性有一定的要求,使用了各种插件和库中的轮播,效果都不是很理想,一怒之下,使用原生JS封装了一个轮播组件,其中重要的功能就是一 ...
- 原生JS封装Ajax插件(同域&&jsonp跨域)
抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...
- 原生JS封装简单动画效果
原生JS封装简单动画效果 一致使用各种插件,有时候对原生JS陌生了起来,所以决定封装一个简单动画效果,熟悉JS原生代码 function animate(obj, target,num){ if(ob ...
- 原生Js封装的弹出框-弹出窗口-页面居中-多状态可选
原生Js封装的弹出框-弹出窗口-页面居中-多状态可选 实现了一下功能: 1.title可自定义 可拖拽 2.width height可以自定义 3.背景遮罩和透明度可以自定义 4.可以自己编辑弹出 ...
随机推荐
- Java API 常用 详解
Runtime类的使用:可以查看内存信息,系统变量,执行系统软件命令,备份数据库相关操作
- svnkit递归获取指定目录下的全部文件
package demo.wc; import java.util.Collection; import java.util.Iterator; import org.tmatesoft.svn.co ...
- MyCAT详解
一.MyCAT概述 MyCAT是一款由阿里Cobar演变而来的用于支持数据库读写分离.分片的分布式中间件.MyCAT可不但支持Oracle.MSSQL.MYSQL.PG.DB2关系型数据库,同时也支持 ...
- SVN学习---使用 Visual SVN 搭建SVN服务器
1.1. 使用 Visual SVN 搭建SVN服务器 搭建纯粹SVN服务器 --- svn:// 访问资源 将SVN 和 Apache服务器整合 ,搭建web SVN服务器 ---- https: ...
- 在vs2015中使用附加进程的方式调试IIS中的页面
发布网站至IIS-附加到进程调试 Internet Information Services(IIS,互联网信息服务),是由微软公司提供的基于运行Microsoft Windows的互联网基本服务. ...
- linux 安装pip 和python3
前言: python3应该是python的趋势所在,当然目前争议也比较大,这篇随笔的主要目的是记录在linux6.4下搭建python3环境的过程 以及碰到的问题和解决过程. 另外,如果本机安装了py ...
- phoneGap的Android下编写phonegap 发送短信插件
一.前端代码的编写 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...
- java里面list是引用的好例子
java里面的赋值和引用是不同的,以后要详细总结一下! 看一个例子: public static void main(String[] args) { List<String> list ...
- C/C++心得-结构体
先说句题外话,个人认为,基本上所有的高级语言被设计出来的最终目的是降低软件开发难度,提升软件开发人员素质和团队协作能力,降低软件维护的难度.在学习语言的时候,可以从这么方面来推测各种语言语法设计的原因 ...
- iPhone 耳机在PC电脑上使用方法
把主声道(Master)从正中间调整到最左或者最右就行了