目次
1. 知識ポイントのまとめ
1. callメソッドの機能は次のとおりです。これが指すメソッドを変更します。
2、 sort排序深入
4、DOM映射
二、实现表格排序
1、使用ajax获取数据
2、使用文档碎片绑定数据
3、对表格进行排序
ホームページ ウェブフロントエンド jsチュートリアル ネイティブ JS はテーブルのソートを実装します

ネイティブ JS はテーブルのソートを実装します

Dec 06, 2017 pm 02:52 PM
javascript 選別 シート

私は最近 JS でのテーブル ソートを学んでいましたが、目立たないテーブル ソートが実際に多くの JS の知識を暗示しているとは思いませんでした。この学習プロセスをここに記録します。皆さんにも役立つことを願っています。

完全なテーブルソートには、次の知識ポイントが含まれます:

  • を使用した呼び出しメソッド

  • sortメソッドの詳細

  • データバインディング

  • DOMマッピング

以下は、これらの詳細な知識をまとめたものです。最後にこれらの知識ポイントを組み合わせて、次のテーブルの並べ替えケースを実装します。
ネイティブ JS はテーブルのソートを実装します

完全なケースソースコード: https://github.com/daweihe/JS...

1. 知識ポイントのまとめ

1. callメソッドの機能は次のとおりです。これが指すメソッドを変更します。

call このメソッドは Function.prototype で定義されています。私たちが定義する関数はすべて、Function クラスのインスタンスと見なすことができます。次に、インスタンスの __proto__ 属性を通じてクラスのプロトタイプを見つけることができます。どの関数でも callapply などのメソッドを呼び出すことができます。

まず例を見てみましょう: Function.prototype的方法。我们定义的任何一个函数都可以认为它是Function这个类的一个实例。那么就可以通过实例的__proto__属性找到所属类的原型。任何一个函数都可以调用callapply等方法。

先来看一个例子:

var obj = {
    name : 'JS'
}

function testCall () {
    console.log(this);
}

testCall.call( obj );     // {name: "JS"}
ログイン後にコピー

首先函数testCall通过原型链查找机制找到call方法执行,call方法在执行过程中把调用call方法这个函数实例中的this都改变成call的第一个参数,接下来调用call方法的这个实例函数执行。

看两个题目:

function fn1() {
    console.log(1);
    console.log(this);
}

function fn2() {
    console.log(2);
    console.log(this);
}

fn1.call(fn2);   //this -> fn2
fn1.call.call(fn2);   //这里的call是改变function.__proto__.call的call方法中的this,相当于执行参数
ログイン後にコピー

call方法在执行的时候,call方法的第一个参数是用来改变this的,而从第二个参数开始都是传给调用call的函数的参数。

在非严格模式下,给call方法不传递参数、或者传递null、undefined后,this都是指向window

sum.call(); //window
sum.call(null); //window
sum.call(undefined); //window
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

严格模式下call执行的时候和非严格模式不同:

sum.call(); //undefined
sum.call(null); //null
sum.call(undefined); //undefined
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

下面使用call方法实现一个类数组转换为数组的方法:

function listToArray (likeAry) {
    var ary = [];
    try {
        ary = Array.prototype.slice.call(likeAry);
    } catch (e) {
        for (var i = 0; i < likeAry.length; i ++) {
            ary[ary.length] = likeAry[i];
        }
    }
    return ary;
}
ログイン後にコピー
ログイン後にコピー

和call类似的方法还有apply和bind方法,这里简单总结一下。

apply方法的作用和call方法一模一样,只是传参的形式不太一样,apply将函数的参数用数组包裹起来:

function sum(num1, num2) {
    console.log(num2 + num1);
    console.log(this);
}

sum.apply(null,[100,200]);
ログイン後にコピー
ログイン後にコピー

bind方法同样也是用来改变this关键字的,但是它只是仅仅改变this指向,不立即执行调用this的函数。

function sum(num1, num2) {
    console.log(num2 + num1);
    console.log(this);
}

var obj = {name : &#39;zx&#39;}

var temp = sum.bind(obj);   //temp已经是被改变了this的函数
temp(100,200);              //当我们需要的时候才执行


//或者像这样处理
var temp = sum.bind(null, 100, 200);
temp();
ログイン後にコピー
ログイン後にコピー

bind方法体现了js中的预处理思想。

2、 sort排序深入

我们知道数组的sort方法只能排序10以内的数组。如果需要排序的数组中存在大于10的数字,我们就需要向sort方法中传入回调函数,常见的是这样:

ary.sort(function (a,b) {
    return a - b;
});
ログイン後にコピー
ログイン後にコピー

这样就能实现数组的升序排序。那么这样排序的原理到底是什么呢?

对于传入的两个参数:a代表的是找到的数组中的当前项,b代表的是当前项的后一项。

  • return a -b : 如果a大于b,返回结果,a与b交换位置。如果a小于b,那么a和b位置不变。 这是升序排序

  • return b -a : 如果b大于a,返回结果,a与b交换位置。如果a小于b,那么a和b位置不变。 这是降序排序

了解了基本原理后,对于这样一个二维数组,如何实现按年龄排序?

var persons = [{
    name:&#39;dawei&#39;,
    age:55
},{
    name:&#39;ahung&#39;,
    age:3
},{
    name:&#39;maomi&#39;,
    age:2
},{
    name:&#39;heizi&#39;,
    age:78
},{
    name:&#39;afu&#39;,
    age:32
}];
ログイン後にコピー
ログイン後にコピー

其实很简单:

ary.sort(function(a,b){
    return a.age - b.age;
});
ログイン後にコピー
ログイン後にコピー

如果按姓名排序,则要涉及字符串的localeCompare()方法:

ary.sort(function(a,b){
    return a.name.localeCompare(b.name);
});
ログイン後にコピー
ログイン後にコピー

name.localeCompare()这个方法会根据两个字符串的字母进行比较,如果前一个字符串的第一个字母在24个英文字母中出现的位置比后一个字符串的第一个字符出现的位置靠前,则认定第一个字符串小,返回-1

//ary为需要添加到页面中的数据数组
var op = document.getElementById("box");//获取容器
var myUl = op.getElementsByTagName("ul")[0];//获取列表

var arrLength = ary.length;
for (var i = 0;i < arrLength ; i ++)
{  //动态创建元素
    var oli = document.createElement("li");
    oli.innerHTML = &#39;<span>' + (i + 5) + '</span>' + ary[i].title;
    myUl.appendChild(oli);//动态添加元素
}
ログイン後にコピー
ログイン後にコピー
まず、関数 testCall は、実行プロセス中に、プロトタイプ チェーン検索メカニズムを通じて実行する呼び出しメソッドを見つけます。呼び出しメソッドは、関数内でこれを変更します。 call メソッドを呼び出すインスタンス その後、call の最初のパラメータが呼び出されて、call メソッドのインスタンス関数が実行されます。

2 つの質問を見てください:

var str = "";
for(var i=0; i<ary.length; i++){
    str += &#39;<li>';
    str += '<span>';
    str += (i+5);
    str += '</span>';
    str += ary[i].title;
    str += '</li>';
}

myUl.innerHTML += str;
ログイン後にコピー
ログイン後にコピー

call メソッドが実行されるとき、call メソッドの最初のパラメータはこれを変更するために使用され、2 番目のパラメータから開始して、呼び出しを呼び出す関数に渡されるパラメータです。

非厳密モードでは、呼び出しメソッドにパラメータが渡されない場合、または null または未定義が渡された場合、これは window を指します。

var frg = document.createDocumentFragment();//创建文档碎片
for (var i =0; i <ary.length ;i ++ ){
    var li = document.createElement("li");
    li.innerHTML = '<span>' + ( i + 5 ) + '</span>' + ary[i].title;
    frg.appendChild(li);//将数据动态添加至文档碎片中
}
myUl.appendChild(frg); //将数据一次性添加到页面中
frg = null;  //释放内存
ログイン後にコピー
ログイン後にコピー
厳密モードでの呼び出しの実行は、非厳密モードの実行とは異なります:

<ul id="myul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
以下では、call メソッドを使用して、配列のような配列を配列に変換するメソッドを実装します:

var myul = document.getElementById("myul");
var mylis = myul.getElementsByTagName('li');
    for (var i = mylis.length - 1 ; i >= 0; i --) {
        myul.appendChild(mylis[i]);
    }
console.log(mylis.length);   // 5
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
次のようなメソッドcall には apply メソッドと binding メソッドも含まれていますが、結論から言えばこれらは単純です。

apply メソッドの機能は call メソッドとまったく同じですが、apply は関数のパラメータを配列でラップする形式が異なります。

<ul id="myul">
    <li>5</li>
    <li>4</li>
    <li>3</li>
    <li>2</li>
    <li>1</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
bind メソッドは this キーワードを変更するためにも使用されます。これは this のポイントを変更するだけであり、this を呼び出す関数はすぐには実行されません。

var res = ''; //声明一个全局变量,接收数据
var xhr = new XMLHttpRequest();
xhr.open('get', 'date.txt', false);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        res = JSON.parse(xhr.responseText);
    }
}
xhr.send(null);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
bind メソッドは、js での前処理のアイデアを具体化します。

2. 詳細な並べ替え🎜🎜 配列の sort メソッドは 10 個以内の配列のみを並べ替えることができることがわかっています。並べ替える必要がある配列内に 10 より大きい数値がある場合、コールバック関数を sort メソッドに渡す必要があります。一般的な関数は次のとおりです。 🎜
var frg = document.createDocumentFragment();
for (let i = 0; i < res.length; i++) {
    var tr = document.createElement("tr");
    for (key in res[i]) {
        var td = document.createElement("td");
        td.innerHTML = res[i][key];
        tr.appendChild(td);
    }
    frg.appendChild(tr);
}
tbody.appendChild(frg);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜 このように、配列は昇順にソートできます。では、この並べ替えの背後にある原理は何でしょうか? 🎜🎜渡される 2 つのパラメーターについて: a は見つかった配列内の現在の項目を表し、b は現在の項目の後の項目を表します。 🎜🎜🎜🎜return a -b: a が b より大きい場合、結果を返し、a と b の位置を交換します。 a が b より小さい場合、a と b の位置は変更されません。 これは昇順です🎜🎜🎜🎜return b -a: b が a より大きい場合、結果を返し、a と b の位置を交換します。 a が b より小さい場合、a と b の位置は変更されません。 これは降順です🎜🎜🎜🎜基本原理を理解した後、このような2次元配列の場合、年齢でソートするにはどうすればよいでしょうか? 🎜
//为两列添加点击事件
for (let i = 0; i < ths.length; i++) {
    let curTh = ths[i];
    curTh.sortFlag = -1; //用于对列进行升降序排列
    curTh.index = i; //记录当前点击列的索引,便于排序操作
    if (curTh.className == &#39;sort&#39;) {
        curTh.onclick = function() {
            sort.call(this); //改变排序函数内this的指向,让其指向当前点击列
        }
    }
}


//排序方法
function sort() {
    //对数组元素进行排序
    let target = this; //这里将this取出,因为在sort方法里需要使用该this,但是sort方法里的this是调用方法的数组
    this.sortFlag *= -1; //1 代表升序   -1代表降序
    let ary = listToArray(bodyTrs); //获取body数据
    ary = ary.sort(function(a, b) {
        let one = a.cells[target.index].innerHTML;
        let two = b.cells[target.index].innerHTML;
        let oneNum = parseFloat(one);
        let twoNum = parseFloat(two);

        if (isNaN(oneNum) || isNaN(two)) {
            return one.localeCompare(two) * target.sortFlag;
        } else {
            return (oneNum - twoNum) * target.sortFlag;
        }
    });
    //把排好序的数组重新写入页面
    let frg = document.createDocumentFragment();
    for (let i = 0; i < ary.length; i++) {
        rg.appendChild(ary[i]);
    }
    tbody.appendChild(frg);
    frg = null;

    //点击某列时,要将其他列的排序标志恢复为-1,让下次再点击任意一个标签时都是默认是升序排列
    for (let i = 0; i < ths.length; i++) {
        if (ths[i] != this) {
            ths[i].sortFlag = -1;
        }
    }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜実際は非常に簡単です: 🎜
var obj = {
    name : &#39;JS&#39;
}

function testCall () {
    console.log(this);
}

testCall.call( obj );     // {name: "JS"}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜名前で並べ替える場合、文字列の localeCompare() メソッドが関係します: 🎜
function fn1() {
    console.log(1);
    console.log(this);
}

function fn2() {
    console.log(2);
    console.log(this);
}

fn1.call(fn2);   //this -> fn2
fn1.call.call(fn2);   //这里的call是改变function.__proto__.call的call方法中的this,相当于执行参数
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜name.localeCompare()このメソッドの比較は、24 個の英語文字のうち、前の文字列の最初の文字が後の文字列の最初の文字よりも前に出現する場合、最初の文字が最初に考慮されます。小さい場合は、-1 が返されます。後で出現する場合は、最初の文字列の方が大きいとみなされ、1 が返されます。比較された文字が等しい場合。次に、次の文字を比較します。 🎜🎜この方法は非常に実用的で、漢字の場合、比較のために中国語の文字を中国語のピンインに自動的に変換するためによく使用されます。 🎜🎜3. データバインディング🎜🎜 js では、データバインディングを実装するために、通常、動的バインディングまたは文字列スプライシングが使用されます。 🎜🎜動的バインディング: 🎜
sum.call(); //window
sum.call(null); //window
sum.call(undefined); //window
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜 追加するたびに DOM リフローが発生します。データ量が多すぎると、パフォーマンスに重大な影響を及ぼします。 🎜🎜 DOM リフローと再描画については、この記事を読むことをお勧めします: http://www.css88.com/archives... 🎜🎜文字列の結合: 🎜
sum.call(); //undefined
sum.call(null); //null
sum.call(undefined); //undefined
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜この方法ではリフローが 1 回だけ発生しますが、削除されます。元の要素のすべてのイベントと属性。マウスが移動して背景の色が変わるときにリスト内の li タグのイベントを追加すると、このメソッドはこのイベントを無効にします。 🎜🎜上記 2 つのデータ バインディング方法によって引き起こされる問題を解決するために、ドキュメント フラグメントを使用してデータを追加します。 🎜
function listToArray (likeAry) {
    var ary = [];
    try {
        ary = Array.prototype.slice.call(likeAry);
    } catch (e) {
        for (var i = 0; i < likeAry.length; i ++) {
            ary[ary.length] = likeAry[i];
        }
    }
    return ary;
}
ログイン後にコピー
ログイン後にコピー
🎜これにより、DOM リフローが 1 つだけ発生し、元の既存のイベントが保持されます。 🎜

4、DOM映射

DOM映射机制:所谓映射,就是指两个元素集之间元素相互“对应”的关系。页面中的标签集合和在JS中获取到的元素对象(元素集合)就是这样的关系。如果页面中的HTML标签结构发送变化,那么集合中对应的内容也会跟着自动改变。

<ul id="myul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

对于这样一个列表使用下列脚本:

var myul = document.getElementById("myul");
var mylis = myul.getElementsByTagName('li');
    for (var i = mylis.length - 1 ; i >= 0; i --) {
        myul.appendChild(mylis[i]);
    }
console.log(mylis.length);   // 5
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

将获取到的列表元素反序重新插入ul中,那么ul列表会变成下面这样:

<ul id="myul">
    <li>5</li>
    <li>4</li>
    <li>3</li>
    <li>2</li>
    <li>1</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

我们看到列表的长度依然是5,只是位置颠倒了。这是因为每个li标签和JS中获取的标签对象存在一个对应关系,当某个标签被重新插入到页面中时,页面中对应的标签会移动到插入的位置。这就是DOM映射。

二、实现表格排序

1、使用ajax获取数据

之所以使用动态获取数据,是为了使用文档碎片绑定数据。

var res = ''; //声明一个全局变量,接收数据
var xhr = new XMLHttpRequest();
xhr.open('get', 'date.txt', false);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        res = JSON.parse(xhr.responseText);
    }
}
xhr.send(null);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

此时数据就保存在了res这个全局变量之中。

2、使用文档碎片绑定数据

var frg = document.createDocumentFragment();
for (let i = 0; i < res.length; i++) {
    var tr = document.createElement("tr");
    for (key in res[i]) {
        var td = document.createElement("td");
        td.innerHTML = res[i][key];
        tr.appendChild(td);
    }
    frg.appendChild(tr);
}
tbody.appendChild(frg);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

3、对表格进行排序

这里涉及的点较多

//为两列添加点击事件
for (let i = 0; i < ths.length; i++) {
    let curTh = ths[i];
    curTh.sortFlag = -1; //用于对列进行升降序排列
    curTh.index = i; //记录当前点击列的索引,便于排序操作
    if (curTh.className == &#39;sort&#39;) {
        curTh.onclick = function() {
            sort.call(this); //改变排序函数内this的指向,让其指向当前点击列
        }
    }
}


//排序方法
function sort() {
    //对数组元素进行排序
    let target = this; //这里将this取出,因为在sort方法里需要使用该this,但是sort方法里的this是调用方法的数组
    this.sortFlag *= -1; //1 代表升序   -1代表降序
    let ary = listToArray(bodyTrs); //获取body数据
    ary = ary.sort(function(a, b) {
        let one = a.cells[target.index].innerHTML;
        let two = b.cells[target.index].innerHTML;
        let oneNum = parseFloat(one);
        let twoNum = parseFloat(two);

        if (isNaN(oneNum) || isNaN(two)) {
            return one.localeCompare(two) * target.sortFlag;
        } else {
            return (oneNum - twoNum) * target.sortFlag;
        }
    });
    //把排好序的数组重新写入页面
    let frg = document.createDocumentFragment();
    for (let i = 0; i < ary.length; i++) {
        rg.appendChild(ary[i]);
    }
    tbody.appendChild(frg);
    frg = null;

    //点击某列时,要将其他列的排序标志恢复为-1,让下次再点击任意一个标签时都是默认是升序排列
    for (let i = 0; i < ths.length; i++) {
        if (ths[i] != this) {
            ths[i].sortFlag = -1;
        }
    }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

表格排序应用很常见,在面试中也会有这样的题目。这个小案例做下来,受益匪浅。这是我在学习的某峰学院的JS课程中的一个案例,如果对JS掌握不扎实的同学,欢迎保存:链接: https://pan.baidu.com/s/1jHVy8Uq 密码: v4jk。如果链接失效,加Q群领取:154658901


私は最近 JS でのテーブル ソートを学んでいましたが、目立たないテーブル ソートが実際に多くの JS の知識を暗示しているとは思いませんでした。この学習プロセスをここに記録します。皆さんにも役立つことを願っています。

完全なテーブルソートには、次の知識ポイントが含まれます:

  • を使用した呼び出しメソッド

  • sortメソッドの詳細

  • データバインディング

  • DOMマッピング

以下は、これらの詳細な知識をまとめたものです。最後にこれらの知識ポイントを組み合わせて、次のテーブルの並べ替えケースを実装します。
ネイティブ JS はテーブルのソートを実装します

完全なケースソースコード: https://github.com/daweihe/JS...

1. 知識ポイントのまとめ

1. callメソッドの機能は次のとおりです。これが指すメソッドを変更します。

call このメソッドは Function.prototype で定義されています。私たちが定義する関数はすべて、Function クラスのインスタンスと見なすことができます。次に、インスタンスの __proto__ 属性を通じてクラスのプロトタイプを見つけることができます。どの関数でも callapply などのメソッドを呼び出すことができます。

まず例を見てみましょう: Function.prototype的方法。我们定义的任何一个函数都可以认为它是Function这个类的一个实例。那么就可以通过实例的__proto__属性找到所属类的原型。任何一个函数都可以调用callapply等方法。

先来看一个例子:

var obj = {
    name : &#39;JS&#39;
}

function testCall () {
    console.log(this);
}

testCall.call( obj );     // {name: "JS"}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

首先函数testCall通过原型链查找机制找到call方法执行,call方法在执行过程中把调用call方法这个函数实例中的this都改变成call的第一个参数,接下来调用call方法的这个实例函数执行。

看两个题目:

function fn1() {
    console.log(1);
    console.log(this);
}

function fn2() {
    console.log(2);
    console.log(this);
}

fn1.call(fn2);   //this -> fn2
fn1.call.call(fn2);   //这里的call是改变function.__proto__.call的call方法中的this,相当于执行参数
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

call方法在执行的时候,call方法的第一个参数是用来改变this的,而从第二个参数开始都是传给调用call的函数的参数。

在非严格模式下,给call方法不传递参数、或者传递null、undefined后,this都是指向window

sum.call(); //window
sum.call(null); //window
sum.call(undefined); //window
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

严格模式下call执行的时候和非严格模式不同:

sum.call(); //undefined
sum.call(null); //null
sum.call(undefined); //undefined
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

下面使用call方法实现一个类数组转换为数组的方法:

function listToArray (likeAry) {
    var ary = [];
    try {
        ary = Array.prototype.slice.call(likeAry);
    } catch (e) {
        for (var i = 0; i < likeAry.length; i ++) {
            ary[ary.length] = likeAry[i];
        }
    }
    return ary;
}
ログイン後にコピー
ログイン後にコピー

和call类似的方法还有apply和bind方法,这里简单总结一下。

apply方法的作用和call方法一模一样,只是传参的形式不太一样,apply将函数的参数用数组包裹起来:

function sum(num1, num2) {
    console.log(num2 + num1);
    console.log(this);
}

sum.apply(null,[100,200]);
ログイン後にコピー
ログイン後にコピー

bind方法同样也是用来改变this关键字的,但是它只是仅仅改变this指向,不立即执行调用this的函数。

function sum(num1, num2) {
    console.log(num2 + num1);
    console.log(this);
}

var obj = {name : &#39;zx&#39;}

var temp = sum.bind(obj);   //temp已经是被改变了this的函数
temp(100,200);              //当我们需要的时候才执行


//或者像这样处理
var temp = sum.bind(null, 100, 200);
temp();
ログイン後にコピー
ログイン後にコピー

bind方法体现了js中的预处理思想。

2、 sort排序深入

我们知道数组的sort方法只能排序10以内的数组。如果需要排序的数组中存在大于10的数字,我们就需要向sort方法中传入回调函数,常见的是这样:

ary.sort(function (a,b) {
    return a - b;
});
ログイン後にコピー
ログイン後にコピー

这样就能实现数组的升序排序。那么这样排序的原理到底是什么呢?

对于传入的两个参数:a代表的是找到的数组中的当前项,b代表的是当前项的后一项。

  • return a -b : 如果a大于b,返回结果,a与b交换位置。如果a小于b,那么a和b位置不变。 这是升序排序

  • return b -a : 如果b大于a,返回结果,a与b交换位置。如果a小于b,那么a和b位置不变。 这是降序排序

了解了基本原理后,对于这样一个二维数组,如何实现按年龄排序?

var persons = [{
    name:&#39;dawei&#39;,
    age:55
},{
    name:&#39;ahung&#39;,
    age:3
},{
    name:&#39;maomi&#39;,
    age:2
},{
    name:&#39;heizi&#39;,
    age:78
},{
    name:&#39;afu&#39;,
    age:32
}];
ログイン後にコピー
ログイン後にコピー

其实很简单:

ary.sort(function(a,b){
    return a.age - b.age;
});
ログイン後にコピー
ログイン後にコピー

如果按姓名排序,则要涉及字符串的localeCompare()方法:

ary.sort(function(a,b){
    return a.name.localeCompare(b.name);
});
ログイン後にコピー
ログイン後にコピー

name.localeCompare()这个方法会根据两个字符串的字母进行比较,如果前一个字符串的第一个字母在24个英文字母中出现的位置比后一个字符串的第一个字符出现的位置靠前,则认定第一个字符串小,返回-1

//ary为需要添加到页面中的数据数组
var op = document.getElementById("box");//获取容器
var myUl = op.getElementsByTagName("ul")[0];//获取列表

var arrLength = ary.length;
for (var i = 0;i < arrLength ; i ++)
{  //动态创建元素
    var oli = document.createElement("li");
    oli.innerHTML = &#39;<span>' + (i + 5) + '</span>' + ary[i].title;
    myUl.appendChild(oli);//动态添加元素
}
ログイン後にコピー
ログイン後にコピー
まず、関数 testCall は、実行プロセス中に、プロトタイプ チェーン検索メカニズムを通じて実行する呼び出しメソッドを見つけます。呼び出しメソッドは、関数内でこれを変更します。 call メソッドを呼び出すインスタンス その後、call の最初のパラメータが呼び出されて、call メソッドのインスタンス関数が実行されます。

2 つの質問を見てください:

var str = "";
for(var i=0; i<ary.length; i++){
    str += &#39;<li>';
    str += '<span>';
    str += (i+5);
    str += '</span>';
    str += ary[i].title;
    str += '</li>';
}

myUl.innerHTML += str;
ログイン後にコピー
ログイン後にコピー

call メソッドが実行されるとき、call メソッドの最初のパラメータはこれを変更するために使用され、2 番目のパラメータから開始して、呼び出しを呼び出す関数に渡されるパラメータです。

非厳密モードでは、呼び出しメソッドにパラメータが渡されない場合、または null または未定義が渡された場合、これは window を指します。

var frg = document.createDocumentFragment();//创建文档碎片
for (var i =0; i <ary.length ;i ++ ){
    var li = document.createElement("li");
    li.innerHTML = '<span>' + ( i + 5 ) + '</span>' + ary[i].title;
    frg.appendChild(li);//将数据动态添加至文档碎片中
}
myUl.appendChild(frg); //将数据一次性添加到页面中
frg = null;  //释放内存
ログイン後にコピー
ログイン後にコピー
厳密モードでの呼び出しの実行は、非厳密モードの実行とは異なります:

<ul id="myul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
以下では、call メソッドを使用して、配列のような配列を配列に変換するメソッドを実装します:

var myul = document.getElementById("myul");
var mylis = myul.getElementsByTagName('li');
    for (var i = mylis.length - 1 ; i >= 0; i --) {
        myul.appendChild(mylis[i]);
    }
console.log(mylis.length);   // 5
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
次のようなメソッドcall には apply メソッドと binding メソッドも含まれていますが、結論から言えばこれらは単純です。

apply メソッドの機能は call メソッドとまったく同じですが、apply は関数のパラメータを配列でラップする形式が異なります。

<ul id="myul">
    <li>5</li>
    <li>4</li>
    <li>3</li>
    <li>2</li>
    <li>1</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
bind メソッドは this キーワードを変更するためにも使用されます。これは this のポイントを変更するだけであり、this を呼び出す関数はすぐには実行されません。

var res = ''; //声明一个全局变量,接收数据
var xhr = new XMLHttpRequest();
xhr.open('get', 'date.txt', false);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        res = JSON.parse(xhr.responseText);
    }
}
xhr.send(null);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
bind メソッドは、js での前処理のアイデアを具体化します。

2. 詳細な並べ替え🎜🎜 配列の sort メソッドは 10 個以内の配列のみを並べ替えることができることがわかっています。並べ替える必要がある配列内に 10 より大きい数値がある場合、コールバック関数を sort メソッドに渡す必要があります。一般的な関数は次のとおりです。 🎜
var frg = document.createDocumentFragment();
for (let i = 0; i < res.length; i++) {
    var tr = document.createElement("tr");
    for (key in res[i]) {
        var td = document.createElement("td");
        td.innerHTML = res[i][key];
        tr.appendChild(td);
    }
    frg.appendChild(tr);
}
tbody.appendChild(frg);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜 このように、配列は昇順にソートできます。では、この並べ替えの背後にある原理は何でしょうか? 🎜🎜渡される 2 つのパラメーターについて: a は見つかった配列内の現在の項目を表し、b は現在の項目の後の項目を表します。 🎜🎜🎜🎜return a -b: a が b より大きい場合、結果を返し、a と b の位置を交換します。 a が b より小さい場合、a と b の位置は変更されません。 これは昇順です🎜🎜🎜🎜return b -a: b が a より大きい場合、結果を返し、a と b の位置を交換します。 a が b より小さい場合、a と b の位置は変更されません。 これは降順です🎜🎜🎜🎜基本原理を理解した後、このような2次元配列の場合、年齢でソートするにはどうすればよいでしょうか? 🎜
//为两列添加点击事件
for (let i = 0; i < ths.length; i++) {
    let curTh = ths[i];
    curTh.sortFlag = -1; //用于对列进行升降序排列
    curTh.index = i; //记录当前点击列的索引,便于排序操作
    if (curTh.className == &#39;sort&#39;) {
        curTh.onclick = function() {
            sort.call(this); //改变排序函数内this的指向,让其指向当前点击列
        }
    }
}


//排序方法
function sort() {
    //对数组元素进行排序
    let target = this; //这里将this取出,因为在sort方法里需要使用该this,但是sort方法里的this是调用方法的数组
    this.sortFlag *= -1; //1 代表升序   -1代表降序
    let ary = listToArray(bodyTrs); //获取body数据
    ary = ary.sort(function(a, b) {
        let one = a.cells[target.index].innerHTML;
        let two = b.cells[target.index].innerHTML;
        let oneNum = parseFloat(one);
        let twoNum = parseFloat(two);

        if (isNaN(oneNum) || isNaN(two)) {
            return one.localeCompare(two) * target.sortFlag;
        } else {
            return (oneNum - twoNum) * target.sortFlag;
        }
    });
    //把排好序的数组重新写入页面
    let frg = document.createDocumentFragment();
    for (let i = 0; i < ary.length; i++) {
        rg.appendChild(ary[i]);
    }
    tbody.appendChild(frg);
    frg = null;

    //点击某列时,要将其他列的排序标志恢复为-1,让下次再点击任意一个标签时都是默认是升序排列
    for (let i = 0; i < ths.length; i++) {
        if (ths[i] != this) {
            ths[i].sortFlag = -1;
        }
    }
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜実際は非常に簡単です: 🎜
var obj = {
    name : &#39;JS&#39;
}

function testCall () {
    console.log(this);
}

testCall.call( obj );     // {name: "JS"}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜名前で並べ替える場合、文字列の localeCompare() メソッドが関係します: 🎜
function fn1() {
    console.log(1);
    console.log(this);
}

function fn2() {
    console.log(2);
    console.log(this);
}

fn1.call(fn2);   //this -> fn2
fn1.call.call(fn2);   //这里的call是改变function.__proto__.call的call方法中的this,相当于执行参数
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜name.localeCompare()このメソッドの比較は、24 個の英語文字のうち、前の文字列の最初の文字が後の文字列の最初の文字よりも前に出現する場合、最初の文字が最初に考慮されます。小さい場合は、-1 が返されます。後で出現する場合は、最初の文字列の方が大きいとみなされ、1 が返されます。比較された文字が等しい場合。次に、次の文字を比較します。 🎜🎜この方法は非常に実用的で、漢字の場合、比較のために中国語の文字を中国語のピンインに自動的に変換するためによく使用されます。 🎜🎜3. データバインディング🎜🎜 js では、データバインディングを実装するために、通常、動的バインディングまたは文字列スプライシングが使用されます。 🎜🎜動的バインディング: 🎜
sum.call(); //window
sum.call(null); //window
sum.call(undefined); //window
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜 追加するたびに DOM リフローが発生します。データ量が多すぎると、パフォーマンスに重大な影響を及ぼします。 🎜🎜 DOM リフローと再描画については、この記事を読むことをお勧めします: http://www.css88.com/archives... 🎜🎜文字列の結合: 🎜
sum.call(); //undefined
sum.call(null); //null
sum.call(undefined); //undefined
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
🎜この方法ではリフローが 1 回だけ発生しますが、削除されます。元の要素のすべてのイベントと属性。マウスが移動して背景の色が変わるときにリスト内の li タグのイベントを追加すると、このメソッドはこのイベントを無効にします。 🎜🎜上記 2 つのデータ バインディング方法によって引き起こされる問題を解決するために、ドキュメント フラグメントを使用してデータを追加します。 🎜
function listToArray (likeAry) {
    var ary = [];
    try {
        ary = Array.prototype.slice.call(likeAry);
    } catch (e) {
        for (var i = 0; i < likeAry.length; i ++) {
            ary[ary.length] = likeAry[i];
        }
    }
    return ary;
}
ログイン後にコピー
ログイン後にコピー
🎜これにより、DOM リフローが 1 つだけ発生し、元の既存のイベントが保持されます。 🎜

4、DOM映射

DOM映射机制:所谓映射,就是指两个元素集之间元素相互“对应”的关系。页面中的标签集合和在JS中获取到的元素对象(元素集合)就是这样的关系。如果页面中的HTML标签结构发送变化,那么集合中对应的内容也会跟着自动改变。

<ul id="myul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

对于这样一个列表使用下列脚本:

var myul = document.getElementById("myul");
var mylis = myul.getElementsByTagName('li');
    for (var i = mylis.length - 1 ; i >= 0; i --) {
        myul.appendChild(mylis[i]);
    }
console.log(mylis.length);   // 5
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

将获取到的列表元素反序重新插入ul中,那么ul列表会变成下面这样:

<ul id="myul">
    <li>5</li>
    <li>4</li>
    <li>3</li>
    <li>2</li>
    <li>1</li>
</ul>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

我们看到列表的长度依然是5,只是位置颠倒了。这是因为每个li标签和JS中获取的标签对象存在一个对应关系,当某个标签被重新插入到页面中时,页面中对应的标签会移动到插入的位置。这就是DOM映射。

二、实现表格排序

1、使用ajax获取数据

之所以使用动态获取数据,是为了使用文档碎片绑定数据。

var res = ''; //声明一个全局变量,接收数据
var xhr = new XMLHttpRequest();
xhr.open('get', 'date.txt', false);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        res = JSON.parse(xhr.responseText);
    }
}
xhr.send(null);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

此时数据就保存在了res这个全局变量之中。

2、使用文档碎片绑定数据

var frg = document.createDocumentFragment();
for (let i = 0; i < res.length; i++) {
    var tr = document.createElement("tr");
    for (key in res[i]) {
        var td = document.createElement("td");
        td.innerHTML = res[i][key];
        tr.appendChild(td);
    }
    frg.appendChild(tr);
}
tbody.appendChild(frg);
ログイン後にコピー

3、对表格进行排序

这里涉及的点较多

//为两列添加点击事件
for (let i = 0; i < ths.length; i++) {
    let curTh = ths[i];
    curTh.sortFlag = -1; //用于对列进行升降序排列
    curTh.index = i; //记录当前点击列的索引,便于排序操作
    if (curTh.className == 'sort') {
        curTh.onclick = function() {
            sort.call(this); //改变排序函数内this的指向,让其指向当前点击列
        }
    }
}


//排序方法
function sort() {
    //对数组元素进行排序
    let target = this; //这里将this取出,因为在sort方法里需要使用该this,但是sort方法里的this是调用方法的数组
    this.sortFlag *= -1; //1 代表升序   -1代表降序
    let ary = listToArray(bodyTrs); //获取body数据
    ary = ary.sort(function(a, b) {
        let one = a.cells[target.index].innerHTML;
        let two = b.cells[target.index].innerHTML;
        let oneNum = parseFloat(one);
        let twoNum = parseFloat(two);

        if (isNaN(oneNum) || isNaN(two)) {
            return one.localeCompare(two) * target.sortFlag;
        } else {
            return (oneNum - twoNum) * target.sortFlag;
        }
    });
    //把排好序的数组重新写入页面
    let frg = document.createDocumentFragment();
    for (let i = 0; i < ary.length; i++) {
        rg.appendChild(ary[i]);
    }
    tbody.appendChild(frg);
    frg = null;

    //点击某列时,要将其他列的排序标志恢复为-1,让下次再点击任意一个标签时都是默认是升序排列
    for (let i = 0; i < ths.length; i++) {
        if (ths[i] != this) {
            ths[i].sortFlag = -1;
        }
    }
}
ログイン後にコピー

以上内容就是原生JS实现表格排序,希望能帮助到大家。

js学习总结经典小案例之表格排序

jquery中tablesorter表格排序组件是如何使用的?

js表格排序实例详解(支持int,float,date,string四种数据类型)

以上がネイティブ JS はテーブルのソートを実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Windows 11/10で写真を撮影日ごとに並べ替える方法 Windows 11/10で写真を撮影日ごとに並べ替える方法 Feb 19, 2024 pm 08:45 PM

この記事では、Windows 11/10 で写真を撮影日順に並べ替える方法を紹介し、Windows で写真が日付順に並べ替えられない場合の対処法についても説明します。 Windows システムでは、画像ファイルを見つけやすくするために、写真を適切に整理することが重要です。ユーザーは、日付、サイズ、名前などのさまざまな並べ替え方法に基づいて写真を含むフォルダーを管理できます。さらに、必要に応じて昇順または降順を設定して、ファイルをより柔軟に整理できます。 Windows 11/10 で写真を撮影日で並べ替える方法 Windows で写真を撮影日で並べ替えるには、次の手順に従います。 [ピクチャ]、デスクトップ、または写真を配置する任意のフォルダを開きます。 リボン メニューで、

PPT テーブルに挿入される画像の形式を調整する手順 PPT テーブルに挿入される画像の形式を調整する手順 Mar 26, 2024 pm 04:16 PM

1. 新しい PPT ファイルを作成し、例として [PPT Tips] という名前を付けます。 2. [PPT Tips]をダブルクリックしてPPTファイルを開きます。 3. 例として 2 行 2 列の表を挿入します。 4. 表の境界線をダブルクリックすると、上部ツールバーに[デザイン]オプションが表示されます。 5. [シェーディング]オプションをクリックし、[画像]をクリックします。 6. [画像]をクリックすると、画像を背景にした塗りつぶしオプションダイアログボックスが表示されます。 7. ディレクトリ内で挿入したいトレイを見つけ、「OK」をクリックして画像を挿入します。 8. テーブル ボックスを右クリックして、設定ダイアログ ボックスを表示します。 9. [セルの書式設定]をクリックし、[画像を網掛けとして並べる]にチェックを入れます。 10. [中央]、[ミラー]など必要な機能を設定し、[OK]をクリックします。注: デフォルトでは、表に画像が入力されます。

Outlook でメールを送信者、件名、日付、カテゴリ、サイズで並べ替える方法 Outlook でメールを送信者、件名、日付、カテゴリ、サイズで並べ替える方法 Feb 19, 2024 am 10:48 AM

Outlook には、作業をより効率的に管理するための多くの設定と機能が用意されています。その 1 つは、ニーズに応じてメールを分類できる並べ替えオプションです。このチュートリアルでは、Outlook の並べ替え機能を使用して、送信者、件名、日付、カテゴリ、サイズなどの基準に基づいてメールを整理する方法を学習します。これにより、重要な情報の処理と検索が容易になり、生産性が向上します。 Microsoft Outlook は、電子メールやカレンダーのスケジュールを簡単に一元管理できる強力なアプリケーションです。電子メールの送受信、整理が簡単にできるほか、内蔵のカレンダー機能により今後のイベントや予定を簡単に追跡できます。 Outlo の使い方

売上予測表の作り方 売上予測表の作り方 Mar 20, 2024 pm 03:06 PM

帳票を上手に作成できることは、経理や人事、財務の分野だけでなく、多くの営業職にとっても帳票の作成を学ぶことは非常に重要です。なぜなら、販売に関連するデータは非常に大規模かつ複雑であり、問​​題を説明するために文書に単純に記録することはできないからです。より多くの営業マンがExcelを使った表作成に習熟できるよう、売上予測に関する表作成の課題を編集部が紹介しますので、お困りの友人は必見です! 1. [売上予測・目標設定]xlsmを開き、各テーブルに格納されているデータを分析します。 2. 新規に[空のワークシート]を作成し、[セル]を選択し、[ラベル情報]を入力します。下に[ドラッグ]し、月を[塗りつぶします]。 [その他]のデータを入力し、[

条件に応じて色を自動変更するWPS値の設定方法_条件に応じて色を自動変更するWPSテーブル値の設定手順 条件に応じて色を自動変更するWPS値の設定方法_条件に応じて色を自動変更するWPSテーブル値の設定手順 Mar 27, 2024 pm 07:30 PM

1. ワークシートを開き、[スタート]-[条件付き書式]ボタンを見つけます。 2. [列の選択] をクリックし、条件付き書式を追加する列を選択します。 3. [条件付き書式]ボタンをクリックするとオプションメニューが表示されます。 4. [条件付きルールを強調表示]-[間]を選択します。 5. ルールを入力します: 20、24、濃い緑色のテキストと濃い塗りつぶし。 6. 確認後、選択した列のデータは、設定に従って対応する数値、テキスト、セル ボックスで色付けされます。 7. 競合のない条件付きルールは繰り返し追加できますが、競合するルールの場合、WPS は以前に確立された条件付きルールを最後に追加したルールに置き換えます。 8. [Between] ルール 20 ~ 24 と [Less than] 20 の後にセル列を繰り返し追加します。 9. ルールを変更する必要がある場合は、ルールをクリアしてからルールをリセットします。

Wordの表を合計する方法を知っていますか? Wordの表を合計する方法を知っていますか? Mar 21, 2024 pm 01:10 PM

Word の表で数を数えるという問題に遭遇することがあります。通常、このような問題に遭遇すると、ほとんどの生徒は Word の表を Excel にコピーして計算しますが、黙って電卓を手に取る生徒もいます。簡単に計算する方法はありますか?もちろんありますが、実はWordでも合計額を計算することができます。それで、その方法を知っていますか?今日は、一緒に見ていきましょう!困っている友達はすぐに集めてください。手順の詳細: 1. まず、コンピューターで Word ソフトウェアを開き、処理する必要がある文書を開きます。 (図のように) 2. 次に、(図のように) 合計値が配置されているセルにカーソルを置き、[メニュー バー] をクリックします。

Word の表に自動番号付けまたはシリアル番号を挿入する方法 Word の表に自動番号付けまたはシリアル番号を挿入する方法 Mar 20, 2024 am 09:30 AM

表を作るとき、真っ先に思いつくのがExcelソフトで表を作ることですが、実はWordソフトを使うととても便利なのをご存知ですか?Wordソフトで表を作ると連番を入力する必要がある場合があります。いちいち手で入力するととても面倒です。実はワードソフトには数字や連番を自動で挿入できる機能があるので、エディターで自動で番号を挿入する方法を学びましょう。またはシリアル番号を Word テーブルに挿入します。 1. まず Word 文書を作成し、表を挿入します。 2. 自動シリアル番号または数字を挿入する列またはセルを選択します。 3.「スタート」-「番号」をクリックします。 4. いずれかのスタイル番号を選択します。 5.

Wordで表を縦横に切り替える方法 Wordで表を縦横に切り替える方法 Mar 20, 2024 am 09:31 AM

Word ソフトは私たちにとって欠かせないものであり、頻繁に使用する必要があります。以前 Word ソフトを使用して表を編集する方法を学んだことがあります。しかし、誤って表を縦横に編集してしまった場合、時間を無駄にしたくないのです。 -作成するのですが、テーブルの縦横を変更することはできますか?毛織物?答えはもちろん「はい」です。次に、Word で表を縦横に入れ替える方法をエディターが詳しく紹介しますので、一緒に学びましょう。まず、以下の Word 表の行と列を交換する必要があります。これを行うには、まずテーブル全体を選択し、次に右クリックしてコピー機能を選択する必要があります。ステップ 2: コピーを選択した後、Word を最小化し、Excel テーブルを開き、右クリックして貼り付けを選択し、Exc に貼り付けます。

See all articles