JavaScript一个很奇怪的问题

我直接上代码吧

var paginButton = $('#pagination a');
var x;
function foo() {
    paginButton.click(function(){
        x = paginButton.index($(this));
    });
    return x
}
a = foo();

点击了按钮之后,我在控制台console.log(a)提示的是undefined

于是这样试了试

var newArr = [];
function foo() {
    paginButton.click(function(){
        var $index = paginButton.index($(this));
        newArr.push($index)
    });
    return newArr;
}
a = foo();

同样的我点击了几个按钮之后,在控制台console.log(a),但是这次给我输入了一个数组,
为什么第一种是underfined,而第二次没毛病

阅读 3.5k
7 个回答

不奇怪呀,你要好好理解一下什么是引用。
为了方便说明,假设第一段代码x初始化为{"0":0}

1、 JS是单线程,代码执行不会从一段代码突然打断,跳转到另一端代码去执行。
paginButton.click(...)的意思是定义一个函数,其代码是xxx,并且绑定为事件处理函数。所以执行代码foo()的时候,x = paginButton.index($(this)); 这一句并不会执行。 而上面这段代码还没有执行完,不会突然跳转到这个实践处理函数,所以a = foo();a=x先执行。
等这段代码执行完了,在点击,出发事件处理函数的执行,才执行x = paginButton.index($(this));

所以,a=xx = paginButton.index($(this));之前。

2 、在 JS 所有对象类型的变量都是一个引用,其中保存的不是具体的那个对象,而是一个指针,指向实际保存的对象。

x = paginButton.index($(this)); 意思是x指向后面生成的那一个对象。
a = x;ax 指向了同一个对象。
然后 x = new Object 这样x 指向了新的对象,而a还是原来的值。

如果先执行a=x; ax 都指向了初始的那个对象,然后x = paginButton.index($(this)); x 指向了新的对象。可是a还是指向原来的对象。

但是,如果 newArr
先执行,a=newArr 这样,anewArr 指向了同一个对象。
然后给newArr指向的对象添加值(而不是让newArr指向新的值),也就是给a指向的对象添加值(它们指向同一个对象)。

var x = {"0":1};
var a = x;
x[0] = 2;
a[0]; // 2
x = new Object();
x[0] = 3;
a[0]; // 2

其实两种情况应该是一样的,简单描述一下,按照程序执行顺序

var paginButton = $('#pagination a');
// 0.声明x, 值为undefined
var x;
function foo() {
    // 2.来到这里,绑定事件(只是绑定click)
    paginButton.click(function(){
        x = paginButton.index($(this));
    });
    // 3.x从始至终没有发生赋值,所以还是全局的x,所以返回undefined
    return x
}
a = foo(); // 1.执行foo方法,获取返回值

流程里面可以看出,a还是全局的那个x,所以第一次应该是undefined,当你点击的时候,因为绑定了click事件,所以x会发生变化,但a不会发生变化,因为后面没有赋值操作了,你可以console.log(x)一下。

第二种情况和第一种的区别是newArr是一个引用对象,执行完foo这个方法,anewArr就是指向同一个内存地址,当你点击的时候,newArr会push新值,所以a会同步发生变化。
类似于:

var a = [];
var b = a;
a.push(1);
console.log(a); // [1]
console.log(b); // [1]

第一种:

a = foo();这一行会执行foo()函数,这个函数的内容就是绑定事件(注意并没有执行),并返回值,这个值此时还未定义。所以a=undefined

绑定的事件在点击时才会执行,这个时候再修改x的值。a也是不会变的。

第二种:

点击后执行array.push修改数组值,再输出就是这个数组的新值

Javascript 的 Mutator 方法会改变调用它们的对象自身的值,比如 pushpopshift 等等。

Accessor 方法不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值,比如 concatjoinslice等等。

首先,你应该没有把阻止a标签跳转的默认行为,所有的点击都刷新了页面,所以就跟每点击一样。

第一种情况,你声明了一个变量x,但是没有赋值,则默认赋值undefined,当你点击按钮时发生了跳转刷新了页面,自然得到的是undefined。
改为


paginButton.click(function(e) {
    e.preventDefault();
    var $index = paginButton.index($(this));
    x.push($index)
});
            

第二种情况,你声明了一个数组,经过一轮函数,又返回了这个数组。
改为

paginButton.click(function(e) {
    e.preventDefault();
    x = paginButton.index($(this));
});

因为第一种你返回的是一个值,这个值是同步返回,而click函数是异步执行,所以函数体是先返回值,此时你还没点击,所以为undefined,即使你以后点击了,此时foo只执行一次,返回值已经确定,就是undefined

第二种是一个数组,数组是全局引用的,foo函数执行过后,a就是这个数组,只要你点击过,这个数组就会修改,当然a就会动态修改了

值类型和引用类型的区别啊
首先你var x 根本就不知道什么类型,但是var newArr是数组啊,数组是引用类型啊。

第一个你就绑定了一个事件,x作为返回值怎么会变化。第二个即使你不return newArr,它的值仍然会变化。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题