Home  >  Q&A  >  body text

javascript数组 - Javascript中,伪数组该如何实现,Jquery中该特性使用的多吗?

1、为什么要通过prototype的形式实现呢
2、哪些情况下会返回伪数组

PHP中文网PHP中文网2749 days ago300

reply all(2)I'll reply

  • ringa_lee

    ringa_lee2017-04-10 15:46:25

    你这问题都问得我不知道从哪里答起了。

    伪数组

    伪数组,就是像数组一样有 length 属性,也有 0123 等属性的对象,看起来就像数组一样,但不是数组,比如

    var fakeArray = {
        length: 3,
        "0": "first",
        "1": "second",
        "2": "third"
    };
    
    for (var i = 0; i < fakeArray.length; i++) {
        console.log(fakeArray[i]);
    }

    常见的参数的参数 arguments,DOM 对象列表(比如通过 document.getElementsByTags 得到的列表),jQuery 对象(比如 $("p"))。

    伪数组是一个 Object,而真实的数组是一个 Array

    fakeArray instanceof Array === false;
    Object.prototype.toString.call(fakeArray) === "[object Object]";
    
    var arr = [1,2,3,4,6];
    arr instanceof Array === true;
    Object.prototype.toString.call(arr) === "[object Array]"

    不过有个更简单的办法来判断,用 Array.isArray

    Array.isArray(fakeArray) === false;
    Array.isArray(arr) === true;

    至于什么情况下返回伪数组,完全看库的实现,一般就比如刚才说到的 arguments,DOM对象列表和 jQuery 对象。如果是自己写的呢,多半是因为希望能通过 prototype 扩展一些方法,又不想直接去扩展 Array.prototype,所以就只好模拟一个 Array,也就是伪数组了,比如 jQuery 就是这么干的。

    prototype (原型)

    然后这里就说到了 prototype。javascript 的 OOP 特性是通过原型,也就是 prototype 来实现的。其它语言中,定义一个类的时候,会在类定义中定义一些实例方法或属性,这样所有这个类的实例对象都具有这些方法和属性。然而 javascript 中没有真正的“类”概念,是通过 function 来模拟构建函数,原型对象来定义实例方法和属性来实现的部分 OOP 特性。

    简单的举例说说,比如定义一个 Person 类 function Person() {},它的实例 new Person() 其实是什么方法与没有的,那就通过为 Person 附加一个原型(或者修改其默认原型)来添加方法和属性

    // 代码①
    function Person(name) {
        this._name = name;
    }
    
    Person.prototype.getName = function() {
        return this._name;
    }
    
    Person.prototype.walk = function() {
        console.log(`${this.getName()} is walking`);
    }
    
    var james = new Person("James");
    james.walk();
    var Jack = new Person("Jack");
    jack.walk();
    
    // [console]
    // James is walking
    // Jack is walking

    但是,原型只是实现的一个方法,也可以直接在构建函数中给 this 赋值的方法来实现

    // 代码②
    function Person(name) {
        this._name = name;
        this.getName = function() {
            return this._name;
        }
        this.walk = function() {
            console.log(`${this.getName()} is walking`);
        }
    }
    
    var james = new Person("James");
    james.walk();
    var jack = new Person("Jack");
    jack.walk();
    
    // [console]
    // James is walking
    // Jack is walking

    看起来似乎实现是一样的,但实际呢,上面那个,生成再多实例对象,所使用的方法都是同一个,原型改了,大家都跟着改。而第2种方法,每个实例对象有自己独立的实现,改掉一个(也没法全部改啊),其它的不会跟着改。

    // 代码③,接 代码①
    Person.prototype.walk = function() {
        console.log(`${this.getName()} is walking walking walking ...`);
    }
    james.walk();
    jack.walk();
    // [console]
    // james is walking walking walking ...
    // jack is waling walking walking ...

    至于第 2 段代码,只能改每个对象的 walk 方法了,改了的会变,没改的不会变。

    留个题

    接③,如果有如下代码,会是什么样的结果?

    james.walk = function() {
        console.log(`${this.getName()} walking ... done");
    }
    
    james.walk();
    jack.walk();
    
    delete james.walk;
    james.walk();

    reply
    0
  • PHPz

    PHPz2017-04-10 15:46:25

    常见的有arguments,DOM集合

    arguments

     function f(){
        console.log(arguments);
        console.log(arguments.length);
        console.log(arguments instanceof Array);
    }
    f(1,2,3);

    DOM集合

    会随着DOM节点的变化动态更新

    <ul id="ul">
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var lis = document.getElementsByTagName('li');
         console.log(lis);
        var ul = document.getElementById('ul');
        ul.appendChild(document.createElement('li'));
        console.log(lis);
    </script>

    reply
    0
  • Cancelreply