基于原生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.可以自己编辑弹出 ...
随机推荐
- zookeeper & kafka 集群
http://cloudurable.com/blog/kafka-architecture/index.html 静态解析 cat >> /etc/hosts << EOF ...
- SQL Server ->> SQL Server 2016重要功能改进之 -- INSERT SELECT时并发插入数据
SQL Server 2016对INSERT INTO XXXX SELECT语句进行了优化,在某些情况下可以触发数据的并行插入,但是要求兼容模式是130(SQL Server 2016)以及在插入的 ...
- 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果
学习笔记---Javascript事件Event.IE浏览器下的拖拽效果 1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...
- ASPNET MVC Error 403.14
今天创建了一个新的ASPNET MVC 项目部署到本地, 生成成功后在浏览器中输入URL却发现报这个错 解决办法: 因为我的站点是4.5的,但是我没有设置Application Pool所以当前还是默 ...
- 查询组成员(group)
查询组成员 $groupname = "groupname" $members = (get-adgroup $groupname -properties member).memb ...
- ssh_exchange_identification: Connection closed by remote host
用服务器内网ip连接同子网服务器的时候显示ssh_exchange_identification: Connection closed by remote host 防火墙什么都关闭了,还是显示这个问 ...
- QT的QPropertyAnimation讲解
m_pAnimation->setEasingCurve(QEasingCurve::Linear); //直线风格 m_pAnimation->setLoopCount(-1); //无 ...
- 代码大全读书笔记 Part 1
简单的看了前言,印象最深的还是这本书崇尚"绝不注水"的原则.现实生活中,不仅仅有注水牛肉,瘦肉精的猪肉,很多书籍也是东拼西凑来的内容,不注水的厚书,是十分令人期待的. 第一章:欢迎 ...
- 可变长度参数以及foreach循环原理
语法糖 接下来几篇文章要开启一个Java语法糖系列,所以首先讲讲什么是语法糖.语法糖是一种几乎每种语言或多或少都提供过的一些方便程序员开发代码的语法,它只是编译器实现的一些小把戏罢了,编译期间以特定的 ...
- chromedriver链接
http://npm.taobao.org/mirrors/chromedriver/