美文网首页
2018-01-25 JavaScript:(a==1 &&

2018-01-25 JavaScript:(a==1 &&

作者: 胡諾 | 来源:发表于2018-01-26 09:21 被阅读0次

    第一组:刘聪 JavaScript:(a==1 && a==2 && a==3)能输出true么?(转载)

    JavaScript:(a==1 && a==2 && a==3)能输出true么?

    有人会说,这个问题好奇葩,放在别的语言里,这要是能输出true,估计是见鬼了,但是你别说,放在js中好真有可能。最近在一个人的推特上提了一个问题:
    • 问题:Can (a==1 && a==2 && a==3) ever evaluate to true?
    • 答案:yes


    在这篇文章中,我将解释这段代码的原理:

    const a = {
      num: 0,
      valueOf: function() {
        return this.num += 1
      }
    };
    const equality = (a==1 && a==2 && a==3);
    console.log(equality); // true
    

    你可以打开chorme浏览器,然后打开开发者模式,在console中输入这段代码,你就可以看到输出结果([windows]: Ctrl + Shift + J [mac]: Cmd + Opt + J))(????)

    有什么窍门呢?

    其实也没有,能有的就是js中的两个概念:
    • 隐式转换
    • object的valueOf函数

    隐式转换

    注意:这题里面我们用的是==而不是===,在js中==代表的是等于而不是全等,那么就存在变量的隐式转化问题。这就意味着结果会比我们所期望的更多的可能性。

    valueOf

    JavaScript提供了一种将对象转化为原始值的方法:Object.prototype.valueOf(),默认情况下,返回正在被调用的对象。
    我们举个例子:

    const a = {
      num: 0
    }
    

    我们可以对上述对象使用valueOf方法,他会返回一个对象。

    a.valueOf();
    // {num: 0}
    

    是不是很酷,我们可以用typeOf来检测一下这个输出结果的类型:

    typeof a.valueOf();
    // "object"
    

    为了让valueOf可以更方便将一个对象转化成原始值,我们可以重写他,换种说法就是我们可以通过valueOf来返回一个字符串、数字、布尔值等来代替一个对象,我们可以看以下代码:

    a.valueOf = function() {
      return this.num;
    }
    

    我们已经重写了原生的valueOf()方法,当我们调用valueOf的时候,他会返回a.num。那我们现在运行以下:

    a.valueOf();
    // 0
    

    我们得到0了,这很合理,因为0就是赋给a.num的值。那我们可以来做几个测试:

    typeof a.valueOf();
    // "number"
    
    a.num == a.valueOf()
    // true
    

    很好,但为什么这个很重要呢?
    这很重要,因为当你两种不同类型的遇到相等操作符的时候,js会对其进行类型转化——它企图将操作数的类型转化为类似的。

    在我们的问题中:(a==1 && a==2 && a==3)JavaScript会企图将对象转化成数字的类型,进行比较。当要转化的是一个Object的时候,JavaScript会调用valueOf()方法。

    自从我们改变了valueOf()方法之后,我们能不能做到以下几点呢:

    a == 0
    // true
    

    我们做到了,异常轻松。

    现在我们需要做的的一点是:当我们每次去调用a的值的时候,能改变它。

    幸运的是,在JavaScript中有+=符号。

    +=这个运算符可以轻松的去改变一个的值,我们可以举个简单的例子:

    let b = 1
    console.log(b+=1); // 2
    console.log(b+=1); // 3
    console.log(b+=1); // 4
    

    正如你所见的,我们每次使用加法赋值运算符,可以让我们的变量增加。
    所以我们可以将这个观念用到valueOf()中。

    a.valueOf = function() {
      return this.num += 1;
    }
    

    当我们每次调用valueOf的时候,他会将变量增加1返回给我们。
    随着这个改变,我们来运行下面的代码:

    const equality = (a==1 && a==2 && a==3);
    console.log(equality); // true
    

    这就是它的工作原理。

    记住下面两点:
    • 使用相等操作符,js会做强制类型转化
    • 我们的对象每次调用valueOf()它的值会增加1

    所以比较的时候我们每次都能得到true。
    • 补充第二点的运算过程

    a                     == 1   -> 
    a.valueOf()           == 1   -> 
    a.num += 1            == 1   -> 
    0     += 1            == 1   ->
    1                     == 1   -> true
    a                     == 2   -> 
    a.valueOf()           == 2   -> 
    a.num += 1            == 2   -> 
    1     += 1            == 2   ->
    2                     == 2   -> true
    a                     == 3   -> 
    a.valueOf()           == 3   -> 
    a.num += 1            == 3   -> 
    2     += 1            == 3   ->
    3                     == 3   -> true
    

    转载自:https://juejin.im/post/5a63f9a451882573473ddba4


    第二组:徐晋 Vue.js计算属性computed与$watch

    在模板中绑定表达式是非常便利的,但是它们实际上只用于简单的操作。模板是为了描述视图的结构。在模板中放入太多的逻辑会让模板过重且难以维护。这就是为什么 Vue.js 将绑定表达式限制为一个表达式。如果需要多于一个表达式的逻辑,应当使用计算属性。

    基础例子

    <div id="example">
        a={{ a }}, b={{ b }}
    </div>
    
    var vm = new Vue({
        el: '#example',
        data: {
            a: 1
        },
        computed: {
            // 一个计算属性的 getter
            b: function() {
                // `this` 指向 vm 实例
                return this.a + 1
            }
        }
    })
    

    这里我们声明了一个计算属性 b。我们提供的函数将用作属性 vm.b的 getter。

    console.log(vm.b) // -> 2
    vm.a = 2
    console.log(vm.b) // -> 3
    

    你可以打开浏览器的控制台,修改 vm。vm.b 的值始终取决于 vm.a 的值。

    你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 vm.b 依赖于 vm.a,因此当 vm.a 发生改变时,依赖于 vm.b 的绑定也会更新。而且最妙的是我们是声明式地创建这种依赖关系:计算属性的 getter 是干净无副作用的,因此也是易于测试和理解的。

    计算属性 vs. $watch

    Vue.js 提供了一个方法 $watch,它用于观察 Vue 实例上的数据变动。当一些数据需要根据其它数据变化时, $watch 很诱人 —— 特别是如果你来自 AngularJS。不过,通常更好的办法是使用计算属性而不是一个命令式的 $watch 回调。考虑下面例子:

    <div id="demo">
        {{fullName}}
    </div>
    var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar',
    fullName: 'Foo Bar' } }) vm.$watch('firstName', function (val) { this.fullName
    = val + ' ' + this.lastName }) vm.$watch('lastName', function (val) { this.fullName
    = this.firstName + ' ' + val })
    

    上面代码是命令式的重复的。跟计算属性对比效果更好:

    var vm = new Vue({
        data: {
            firstName: 'Foo',
            lastName: 'Bar'
        },
        computed: {
            fullName: function() {
                return this.firstName + ' ' + this.lastName
            }
        }
    })
    
    计算 setter

    计算属性默认只是 getter,不过在需要时你也可以提供一个 setter:

    // ...
    computed: {
        fullName: {
            // getter
            get: function() {
                return this.firstName + ' ' + this.lastName
            },
            // setter
            set: function(newValue) {
                var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1]
            }
        }
    }
    // ...
    

    现在在调用 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName 也会有相应更新。


    第三组:黄华英 Vue 组件之间的通信

    一、非父子组件之间通信

    vue中的slot分发内容

    当我们在使用vue组件的时候,我们常常要像如下代码一样组合它们:

    <app>
      <app-header></app-header>
      <app-footer></app-footer>
    </app>
    

    为了让组件可以组合,我们需要一种方式来来混合父组件的内容和子组件的模板,这个过程被叫做内容分发,我们通过<slot>元素作为原始内容的插槽的方式来实现。注意:父组件模板的内容应该就要在父组件 作用域内编译,子组件模板的内容应该在子组件作用域内编译。

    <!-- 无效,应为someChildProperty是子组件的属性 -->
    <child-component v-show="someChildProperty"></child-component>
    Vue.component('child-component', {
       // 有效,因为是在正确的作用域内
      template: '<div v-show="someChildProperty">Child</div>',
      data: function () {
        return {
          someChildProperty: true
        }
      }
    })
    

    在进行内容分发的时候子组件至少要有一个slot插槽,否则父组件中的内容将被丢弃。当子组件只有一个slot插槽的时候父组件的所有内容片断都将要插入子组件的slot插槽s所在DOM位子上,并替换掉slot插槽标签本身。

    假设子组件模板my-component如下:

    <div>
      <h2>我是子组件的标题</h2>
      <slot>
        只有在父组件没有要分发的内容时才会显示。
      </slot>
    </div>
    

    父组件模板如下:

    <div>
      <h1>我是父组件的标题</h1>
      <my-component>
    <!-- 以下内容会进行分发到子组件模板上,如果子组件的模板没有slot插槽,那么内容会被抛弃,如果有一个slot插槽那么以下内容会替换掉slot插槽所在的DOM位子 -->
        <p>这是一些初始内容</p>
        <p>这是更多的初始内容</p>
      </my-component>
    </div>
    

    最终渲染的结果为:

    <div>
      <h1>我是父组件的标题</h1>
      <div>
        <h2>我是子组件的标题</h2>
        <p>这是一些初始内容</p>
        <p>这是更多的初始内容</p>
      </div>
    </div>
    

    如果子组件有多个slot插槽的情况下我们可以通过具名slot将父组件的内容分别分发到子组件的对应名称的slot插槽上面。

    子组件:

    <div class="container">
      <header>
        <slot name="header"></slot>
      </header>
      <main>
        <slot></slot>
      </main>
      <footer>
        <slot name="footer"></slot>
      </footer>
    </div>
    

    父组件:

    <app-layout>
      <h1 slot="header">这里可能是一个页面标题</h1>
      <p>主要内容的一个段落。</p>
      <p>另一个主要段落。</p>
      <p slot="footer">这里有一些联系信息</p>
    </app-layout>
    

    最终渲染的结果:

    <div class="container">
      <header>
        <h1>这里可能是一个页面标题</h1>
      </header>
      <main>
        <p>主要内容的一个段落。</p>
        <p>另一个主要段落。</p>
      </main>
      <footer>
        <p>这里有一些联系信息</p>
      </footer>
    </div>
    

    第四组:王芳 互换城市

    过年在携程买票的时候,偶然间发现点击城市中间的图标可以将出发城市和到达城市互换,于是我去官网找了一下实现代码,具体如下:

    1. 效果:点击图标互换城市


    1. HTML结构:给img设置一个ID,href="javascript:;"可以阻止a标签的默认行为


    2. JavaScript:


    3. 源代码:

    $("#citySwap").on("click", function () {
        var temp = $("#startCity").val();
        $("#startCity").val($("#endCity").val());
        $("#endCity").val(temp);
        var tempsegnum = $("#startCity").attr("segnum");
        $("#startCity").attr("segnum", $("#endCity").attr("segnum"));
        $("#endCity").attr("segnum", tempsegnum);
    })
    

    第五组:王颢 XtraTreeList控件的使用中几个问题

    1.repositoryItemComboBox下拉表不能显示

    通过repositoryItemComboBox的click事件,向其动态add下拉列表中的items后,点击 repositoryItemComboBox的下拉按钮,下拉列表闪一下就消失了(不是在click事件中添加items的情况,不会出现此问题)。解 决方案,在repositoryItemComboBoxButtonClick事件中,将事件源sender转换为ComboBoxEdit,再利用 add函数添加item,最后手动显示下拉列表,代码如下:

    ComboBoxEdit combo = sender as ComboBoxEdit;            combo.Properties.Items.Add(…);
    combo.ShowPopup();
    

    2.DevExpress.XtraTreeList设置焦点函数setFocusedNode()无效

    当使用TreeListNode addedNode = treeList1.AppendNode(参数略),向tree中添加一个节点后,一 般想立刻使这个新添加的节点获得焦点,但此时如果直接使用treeList1.SetFocusedNode(addedNode)则无效,可能是因为 addedNode中不包含tree为其分配的nodeID(猜测),解决方案是 treeList1.SetFocusedNode(treeList1.FindNodeByKeyID(stateID));即利用findnode之类的函数去查询tree,找到新添加的结点,在将该节点作为SetFocusedNode的参数,则可以完成焦点的设置。

    1. DevExpress.XtraTreeList查找结点函数FindNodeByKeyID()无效

    treefind这类函数,在进行查找时,需要注意参数的类型,例如,这个函数FindNodeByKeyID()是根据数据源里的主键进行结点查 找,即你需要给定tree对应数据源中的记录的key,如果数据源中的key是整型,而我们利用一个字符串类型作为参数的 话, FindNodeByKeyID(”100”)将不能找到节点,正确的写法应该是FindNodeByKeyID(100)

    WinForm设置控件焦点

    winform窗口打开后文本框的默认焦点设置,进入窗口后默认聚焦到某个文本框,两种方法:

    ①设置tabindex
    把该文本框属性里的tabIndex设为0,焦点就默认在这个文本框里了。

    ②Winform的Activated事件
    在Form的Activated事件中添加textBox1.Focus(), 即可获得焦点。

    private void Form1_Activated(object sender, EventArgs e) 
    { 
        textBox1.Focus(); 
    }
    

    TextBox是可以获得焦点的. 有几个前提:

    1. TextBox所属的窗体(Form)在可操作(Active)状态. 即用户选中了Form.
    2. TextBox的Enable属性,Visiable属性为True.
      刚开始时原以为在Form的Load事件中添加textBox1.Focus(),测试失败
    private void Form1_Load(object sender, EventArgs e) 
    { 
        textBox1.Focus(); 
    }
    

    因为在窗体加载时调用Focus()函数时, TextBox还未能成功的被显示到界面上。所以导致了失败。

    相关文章

      网友评论

          本文标题:2018-01-25 JavaScript:(a==1 &&

          本文链接:https://www.haomeiwen.com/subject/miliaxtx.html