Giter VIP home page Giter VIP logo

first-things's Introduction

first-things

没事别fork,除非要修改;千万不要watch,否则各种动态消息邮箱连环轰炸;最好的就是star。

plan

打算在github pages上写作业,issue上记笔记。

first-things's People

Contributors

zxq-guren avatar

Watchers

James Cloos avatar

first-things's Issues

jquery-validation表单验证插件

jquery validate是最流行的表单验证插件之一

主要作用:丰富的表单验证,什么邮件,链接,还可以自定义各种规则,提示等,基本上能满足所有的表单验证;

使用就直接导入库文件jquery-1.11.1.js、jquery.validate.js
方法:

1.用其他事件取代submit默认事件:

$("myform").validate{(
    submitHandler:function(form){
        console.log("submit");
        form.submit();//默认的submit事件 ;
    }
)}

2.debug 调试的时候使用,只检查表单,不提交

 $("#myform").validate({
        debug:true
    });

3.ignore:忽略某些元素不验证

ignore:".ignore"//类名为ignore的元素不验证

4.自定义错误信息样式(css–加在css样式中)

input.error { border: 1px solid red; }
label.error {
    background:url("./demo/images/unchecked.gif") no-repeat 0px 0px;
    padding-left: 16px;
    padding-bottom: 2px;
    font-weight: bold;
    color: #EA5200;
}
label.checked {
    background:url("./demo/images/checked.gif") no-repeat 0px 0px;
}

5.每个字段验证通过调用的函数(比如输入框验证后可以在后面加个勾)

success: function(label) {
    // set   as text for IE
    label.html(" ").addClass("checked");
    //label.addClass("valid").text("Ok!")
}

6.验证的触发方式修改(都是boolean类型) 除了focusCleanup默认为false其他都默认true;

onsubmit    提交时验证。设置为 false 就用其他方法去验证。  
onfocusout  失去焦点时验证(不包括复选框/单选按钮)。   
onkeyup     在 keyup 时验证。    
onclick     在点击复选框和单选按钮时验证。     
focusInvalid    提交表单后,未通过验证的表单会获得焦点。    
focusCleanup    如果是 true 那么当未通过验证的元素获得焦点时,移除错误提示。避免和 focusInvalid 一起用。

面试题<一>

面试题

请写出 Ajax 请求中用到的函数

var xhr = new XMLHttpRequest();
xhr.open('GET/POST', 'http://localhost:8080?username=meishadevs', true);
xhr.onreadystatechange = function() {};
xhr.send();

使用正则表达式提取出url值为 https://map.baidu.com/x/y/z 中的 map.baidu.com

/https:\/\/([^\/]+)/.exec('https://map.baidu.com/x/y/z')[1]

'https://map.baidu.com/x/y/z'.match(/https:\/\/([^\/]+)/)[1]
// "map.baidu.com"

设计一个函数实现add(3)(4) , 什么是函数柯里化?

柯里化:在一个函数中首先填充几个参数(然后再返回一个新函数)的技术称为柯里化(Currying)
参考从一道面试题谈谈函数柯里化(Currying)
柯里化(Currying)具有:延迟计算、参数复用、动态生成函数的作用

//
function add(a) {
    return function(b) {
        return a + b;
    }
}

add(3)(4)

//ES6写法
add = a => b => a + b
add(3)(4)

//
//函数表达式定义
var add = function(x){
    return function(y){
        return x + y;
    }
};
//函数调用
add(3)(4);

使用Ajax实现一个表单提交功能,并跳转到提交的地址,(可以使用 jQuery 或 Zepto)

var link={            //jQuery的AJAX执行的配置对象
      type:"GET",      //设置请求方式,默认为GET,
      async:true,      //设置是否异步,默认为异步
      url:"customback.php",
      dataType:"json",    //设置期望的返回格式,因服务器返回json格式,这里将数据作为json格式对待
      success:function (msg){
            process...

            setTimeout("link()",300);
      }              //成功时的回调函数,处理返回数据,并且延时建立新的请求连接
}
$.ajax(link);          //执行ajax请求。

使用 Promise 再实现一遍

var getJSON = function(url) {
  var promise = new Promise(function(resolve, reject){
    var client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

    function handler() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
  });

  return promise;
};

getJSON("http://rap.taobao.org/mockjs/9768/Rap/get").then(function(response) {
  console.log('Contents: ',response);
}, function(error) {
  console.error('出错了', error);
});

标准盒模型和怪异盒模型的区别

标准盒模型的 box-sizing 属性的值为 content-box
怪异盒模型的 box-sizing 属性的值为 border-box
标准盒模型中 width = 内容的宽度
怪异盒模型中 width = 内容的宽度 + padding + border

em 与 rem 的区别

rem 表示根节点(html标签)的字体大小的倍数
当 em 作为 font-size 的单位时,表示相对于父元素的 font-size 值的倍数
当 em作为其他属性单位时,代表自身字体大小的倍数

元素层叠

参考张鑫旭大神的文章:深入理解CSS中的层叠上下文和层叠顺序

设计一个函数实现判断一个数据的数据类型是不是数组

function isArray(num) {
    return num instanceof Array;
}

使用原型现继承

使用 proto 实现继承

//创建animal对象
var animal = {
    name: "animal",

    eat: function () {
        console.log(this.name + " is eating");
    }
};

//创建dog对象
var dog = {
    name: "dog",

    //指向animal对象(dog继承自animal)
    __proto__: animal
};

//创建cat对象
var cat = {
    name: "cat",

    //指向animal对象(cat继承自animal)
    __proto__: animal
};

dog.eat();
cat.eat();

使用 prototype 实现继承


//创建animal对象
var animal = {
    name: "animal",

    eat: function () {
        console.log(this.name + " is eating");
    }
};

//创建构造函数Dog
function Dog() {
    this.name = "dog";
}

//创建构造函数Cat
function Cat() {
    this.name = "cat";
}

//设置Dog的原型为animal(Dog继承自animal)
Dog.prototype = animal;

//设置Cat的原型为animal(Cat继承自animal)
Cat.prototype = animal;

//创建dog对象
var dog = new Dog();

//创建cat对象
var cat = new Cat();

dog.eat();
cat.eat();

解决css中float引起父元素高度塌陷问题的方法

虽然现在很多人都推荐用Flex布局来替代浮动布局,但是IE11以下和一些低级别版本的浏览器对Flex的支持不太好,所以我们用好浮动布局还是很有必要的。这篇文章主要是解决float引起父元素高度塌陷问题,设置浮动,父容器没有撑开,以下是这几种解决方法:

一、缘由

<style>
     .content{
         background-color: rgba(102, 102, 102, 0.35);
     }
     h1,p{
         /*float:left;*/
     }
     p{
         margin-top: 1rem;
         font-size: 1rem;
     }
    div { background-color: red}
</style>

<body>
<div class="content">
<div>   
<h1>沉默的大多数</h1>
    <p>  我现在写的东西大体属于文学的范畴,所谓文学,在我看来就是:先把文章写好看了再说,别的就不用管他妈的。除了文学,
        我想不到有什么地方可以接受我这些古怪想法。赖在文学上,可以给自己在圈子中找到一个立脚点。</p>
    <p>几年前,我在美国读书。有个洋鬼子这样问我们:你们**那个阴阳学说,怎么一切好的东西都属阳,一点不给阴剩下?当然,她这样发问,是因为她正是一个五体不全之阴人。但是这话也有些道理。话语权属于阳的一方,它当然不会说阴的一方任何好话。就是夫子也未能免俗,他把妇女和小人攻击了一通。
        至于怎样不做妇人,这问题一直没有解决。就是到了现代,女变男的变性手术也是一个难题,而且也不宜推广——这世界上假男人太多,真男人就会找不到老婆。</p>
</div>
</body>

可以很明显的看到背景没有了,父容器的高度变为0px了,这是为什么呢?因为元素浮动之后,周围的元素会重新排列,浮动的元素就跟浮云一样,不会影响到我们地面上的人类(未浮动的元素),人类怎么排列和漂浮的云没有关系。那该如何解决?

二、解决方法

1.在父元素底部加一行代码
我们在父元素底部增加了一行空的div标签,并且为其设置了样式
clear:both;

<body>
<div class="content">
    <h1>沉默的大多数</h1>
    <p>  我现在写的东西大体属于文学的范畴,所谓文学,在我看来就是:先把文章写好看了再说,别的就不用管他妈的。除了文学,
        我想不到有什么地方可以接受我这些古怪想法。赖在文学上,可以给自己在圈子中找到一个立脚点。有这样一个立脚点,就可以攻击这个圈子,攻击整个阳的世界。</p>
    <p>几年前,我在美国读书。有个洋鬼子这样问我们:你们**那个阴阳学说,怎么一切好的东西都属阳,一点不给阴剩下?当然,她这样发问,是因为她正是一个五体不全之阴人。但是这话也有些道理。话语权属于阳的一方,它当然不会说阴的一方任何好话。就是夫子也未能免俗,他把妇女和小人攻击了一通。这句话几千年来总被人引用,但我就没听到受攻击一方有任何回应。人们只是小心提防着不要做小人,
        至于怎样不做妇人,这问题一直没有解决。就是到了现代,女变男的变性手术也是一个难题,而且也不宜推广——这世界上假男人太多,真男人就会找不到老婆。</p>
<div style="clear:both;"></div>
</div>
</body>

这种方法通俗易懂,也容易掌握。
但是缺点是添加了无意义的空标签,违背了结构表现分离,给后期维护带来了问题。
2.给父元素增加一行css代码

 div.content{
       float:left;
  }

这招”将错就错”,父元素本来就不需要浮动,为了解决高度问题让父元素浮动又会引发其他问题。
3.利用BFC来给父元素增加CSS

 div.content{
       overflow:auto;
  }

上面只是一种做法,你还可以加display:table-cell;display:table-caption;display:inline-block;position:fixed;position:absolute等等,你要问我为什么它们可以清除浮动,其实这些都是触发了BFC(块级格式化上下文具体的我不解释了,大家可以看看这篇文章BFC神器背后的原理
4.使用CSS中的after伪元素
使用css中给父元素div添加一个clearfix的class类,

,然后设置CSSafter伪类

  .clearfix:after{
        content: ".";
        display: block;
        height: 0px;
        clear: both;
        visibility: hidden;
   }  

这种方法其实有点类似于第一种方法,不过这种方法是通过after伪元素来给父元素末尾添加一个看不见的clear:both;的块元素,来达到清除浮动的目的。其中 content: ".";是为了加一段内容,display: block;是为了让生成的元素以块级元素显示,占满剩余空间,height: 0px;是为了避免生成的内容避免原有布局的高度, visibility: hidden;是为了让生成的元素不可见。
5.最后一招--索尼大发

.clearfix:after,
.clearfix:before{
      content: " ";
      display: table; 
}  
.clearfix:after{
      clear: both;
}

上述代码把display设置为table,可以创建一个匿名的表格单元,这个匿名的表格单元可以直接触发BFC,然后再直接设置content: " ";,把内容设置为一个空格,这样就节省了不必要的代码。
那加before伪元素是为了什么呢?加上before对于清除浮动没有什么必要性,主要目的是防止浏览器顶部的空白崩溃,即是指此盒子的margin-top与上一个盒子的margin-bottom会发生折叠,(在同一个BFC中两个毗邻的块级盒子在垂直方向(和布局有关系)的margin会发生折叠)。

转载作者:爱嘎的Front_end
链接:https://www.jianshu.com/p/3e0a2bde9051

小程序总结二

组件

swiper 组件

<view>
  <swiper indicator-dots="true" autoplay="true" interval="5000" circular="true">  
    <swiper-item>
      <image src="/images/post/[email protected]" />
    </swiper-item>
    <swiper-item>
      <image src="/images/post/[email protected]" />
    </swiper-item>
    <swiper-item>
      <image src="/images/post/[email protected]" />
    </swiper-item>
  </swiper>
</view>
  • swiper 组件是一个滑块视图容器,其直接子元素只能是 swiper-item,swiper-item 下可以防止其他组件或元素
  • 需要同时设置 swiper 组件和 image 组件的宽高,才能使得图片达到预期效果,而对 swiper-item 设置宽高是没有用的,
    整个 组件的宽高必须设在 swiper 的根节点,而 swiper-item 作为 swiper 的子集,它的默认宽高取的就是 swiper 的宽高
  • 官方 API 文档:swiper-item 仅可放置在 swiper 组件中,宽高自动设置为 100%

更多参考 官方 API 文档

  • vertical,这个属性将指明 swiper 组件面板指示点的排布方向,在 swiper 组件中加入 vertical="true",
    面板指示点由原来的水平排版更改为竖直排布,并且轮播图也改为纵向滚动
  • 属性的布尔值有一点需要注意的是,如果你设为 vertical="false",面板指示点还是会呈现竖直排布,不管你将属性值改为任何字符串,它依旧是竖直排布,
    因为这里的 false,指的是字符串,而并非是布尔值,若是想让面板指示点水平排布,有以下几种方式:
    ① 不加入 vertical 属性;
    ② vertical=" ";
    ③ vertical="{{false}}"

image 组件

实际项目里,绝大部分的情况下,图片保持比例、允许裁切是最普遍的需求

小程序的 image 组件提供了 4 种缩放模式和 9 种裁剪模式

4 种缩放模式

模式 值 说明
缩放 scaleToFill 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
缩放 aspectFit 保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。
缩放 aspectFill 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
缩放 widthFix 宽度不变,高度自动变化,保持原图宽高比不变

9 种裁剪模式

模式 值 说明
裁剪 top 不缩放图片,只显示图片的顶部区域
裁剪 bottom 不缩放图片,只显示图片的底部区域
裁剪 center 不缩放图片,只显示图片的中间区域
裁剪 left 不缩放图片,只显示图片的左边区域
裁剪 right 不缩放图片,只显示图片的右边区域
裁剪 top left 不缩放图片,只显示图片的左上边区域
裁剪 top right 不缩放图片,只显示图片的右上边区域
裁剪 bottom left 不缩放图片,只显示图片的左下边区域
裁剪 bottom right 不缩放图片,只显示图片的右下边区域

 <image class="post-image" src="/images/post/post-5.jpg" mode="aspectFill" />

事件委托或事件代理的详解(冒泡原理)

转载:http://www.cnblogs.com/liugang-vip/p/5616484.html
作为前端面试经典的题型,相信肯定是个不错的案例。

什么叫事件委托?

在javascript高级程序设计中讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。详细通过经典的例子:取快递来解释。
有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。

这里其实还有2层意思的:

第一,现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;

第二,新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的

事件委托的原理:

事件委托是利用事件的冒泡原理来实现,何为事件冒泡?就是事件从最深的节点开始,然后逐步向上传播事件。举个例子:页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。

事件委托优点

一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了。
在javascript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行能力,因为需要不断的与DOM节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要**是就是减少dom操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样大大的减小与dom的交互次数,提高性能。
简单的说就是只访问它的父级(如果只有一个父级)这个对象进行操作可以满足访问到父级中任何子对象的操作,是不是大大的减少访问的次数。

事件委托怎么实现?

Event对象提供了一个属性叫target,可以返回事件的目标节点,我们成为事件源,也就是说,target就可以表示为当前的事件操作的dom,但是不是真正操作dom,当然,这个是有兼容性的,标准浏览器用ev.target,IE浏览器用event.srcElement,此时只是获取了当前节点的位置,并不知道是什么节点名称,这里我们用nodeName来获取具体是什么标签名,这个返回的是一个大写的,我们需要转成小写再做比较(习惯问题):

`
window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    if(target.nodeName.toLowerCase() == 'li'){
         alert(123);
        alert(target.innerHTML);
    }
  }
}

只有点击li就会触发事件了,且每次只执行一次dom操作,如果li数量很多的话,将大大减少dom的操作,优化的性能可想而知。

如果要每次li被点击的效果都不一样,那用事件委托还有用?

<div id="box">
        <input type="button" id="add" value="添加" />
         <input type="button" id="remove" value="删除" />
         <input type="button" id="move" value="移动" />
         <input type="button" id="select" value="选择" />
</div>

window.onload = function(){
var Add = document.getElementById("add");
var Remove = document.getElementById("remove");
var Move = document.getElementById("move");
var Select = document.getElementById("select");

        Add.onclick = function(){
            alert('添加');
        };
        Remove.onclick = function(){
            alert('删除');
        };
        Move.onclick = function(){
            alert('移动');
        };
        Select.onclick = function(){
            alert('选择');
        }
        
    }

上面传统的方法,4个按钮,点击每一个做不同的操作,那么至少需要4次dom操作,如果用事件委托,能进行优化吗?

window.onload = function(){
            var oBox = document.getElementById("box");
            oBox.onclick = function (ev) {
                var ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                if(target.nodeName.toLocaleLowerCase() == 'input'){
                    switch(target.id){
                        case 'add' :
                            alert('添加');
                            break;
                        case 'remove' :
                            alert('删除');
                            break;
                        case 'move' :
                            alert('移动');
                            break;
                        case 'select' :
                            alert('选择');
                            break;
                    }
                }
            }
            
        }

用事件委托就可以只用一次dom操作就能完成所有的效果,比上面的性能肯定是要好一些的 。
现在讲的都是document加载完成的现有dom节点下的操作,那么如果是新增的节点,新增的节点会有事件吗?也就是说,一个新员工来了,他能收到快递吗?
看一下正常的添加节点的方法:

<input type="button" name="" id="btn" value="添加" />
    <ul id="ul1">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
    </ul>
window.onload = function(){
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            //鼠标移入变红,移出变白
            for(var i=0; i<aLi.length;i++){
                aLi[i].onmouseover = function(){
                    this.style.background = 'red';
                };
                aLi[i].onmouseout = function(){
                    this.style.background = '#fff';
                }
            }
            //添加新节点
            oBtn.onclick = function(){
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
            };
        }

这是一般的做法,但是你会发现,新增的li是没有事件的,说明添加子节点的时候,事件没有一起添加进去,这不是我们想要的结果,那怎么做呢?一般的解决方案会是这样,将for循环用一个函数包起来,命名为mHover,如下:

window.onload = function(){
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            function mHover () {
                //鼠标移入变红,移出变白
                for(var i=0; i<aLi.length;i++){
                    aLi[i].onmouseover = function(){
                        this.style.background = 'red';
                    };
                    aLi[i].onmouseout = function(){
                        this.style.background = '#fff';
                    }
                }
            }
            mHover ();
            //添加新节点
            oBtn.onclick = function(){
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
                mHover ();
            };
        }

虽然功能实现了,看着还挺好,但实际上无疑是又增加了一个dom操作,在优化性能方面是不可取的,那么有事件委托的方式,能做到优化吗?

window.onload = function(){
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            //事件委托,添加的子元素也有事件
            oUl.onmouseover = function(ev){
                var ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                if(target.nodeName.toLowerCase() == 'li'){
                    target.style.background = "red";
                }
                
            };
            oUl.onmouseout = function(ev){
                var ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                if(target.nodeName.toLowerCase() == 'li'){
                    target.style.background = "#fff";
                }
                
            };
            
            //添加新节点
            oBtn.onclick = function(){
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
            };
        }

看,上面是用事件委托的方式,新添加的子元素是带有事件效果的,我们可以发现,当用事件委托的时候,根本就不需要去遍历元素的子节点,只需要给父级元素添加事件就好了,其他的都是在js里面的执行,这样可以大大的减少dom操作,这才是事件委托的精髓所在。

总结:

那什么样的事件可以用事件委托,什么样的事件不可以用呢?

适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。

值得注意的是,mouseover和mouseout虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。

不适合的就有很多了,举个例子,mousemove,每次都要计算它的位置,非常不好把控,在不如说focus,blur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。

面试题<二>

认清现状:

  1. 大部分公司(创业公司)都趋向于招一个牛逼的前端而不是三四个平庸的前端
  2. 性能优化、ES6必问
  3. 招聘要求上清一色的要求有一门后端语言的经验,但似乎面试的时候并没有一个公司问过我后端语言方面的东西

ES6考点

1.使用箭头函数需要注意的地方

当要求动态上下文的时候,你就不能使用箭头函数,比如:定义方法,用构造器创建对象,处理时间时用 this 获取目标。

2.ES6 let、const

let


let是更完整的Var

  1. let声明的变量拥有块级作用域,let声明仍然保留了提升的特性,但不会盲目提升。
  2. let声明的全局变量不是全局对象的属性。不可以通过window.变量名的方式访问
  3. 形如for (let x…)的循环在每次迭代时都为x创建新的绑定
  4. let声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在到达之前使用该变量会触发错误。

const


定义常量值,不可以重新赋值,但是如果值是一个对象,可以改变对象里的属性值

const OBJ = {"a":1, "b":2};
OBJ.a = 3;
OBJ = {};// 重新赋值,报错!
console.log(OBJ.a); // 3

HTML与css考点

1.说说HTML5中有趣的标签(新标签及语义化)

如果代码写的语义化,有利于SEO。搜索引擎就会很容易的读懂该网页要表达的意思。例如文本模块要有大标题,合理利用h1-h6,列表形式的代码使用ul或ol,
重要的文字使用strong等等。总之就是要充分利用各种HTML标签完成他们本职的工作

2.怎么让一个不定宽高的 DIV,垂直水平居中?

使用Flex

  • 只需要在父盒子设置:display: flex; justify-content: center;align-items: center;
    使用 CSS3 transform
  • 父盒子设置:position:relative
  • Div 设置: transform: translate(-50%,-50%);position: absolute;top: 50%;left: 50%;
    使用 display:table-cell 方法
  • 父盒子设置:display:table-cell; text-align:center;vertical-align:middle;
  • Div 设置: display:inline-block;vertical-align:middle;

3.position 几个属性的作用

JavaScript是一种弱类型语言,有什么优点和缺点

弱类型语言都是脚本语言,在运行时确定值,所以跟编译不相关。

弱类型语言内存布局上一般是个Union结构,并且要包含一个类型字段,因为计算机底层还是要知道明确的类型信息

强类型语言是直接操纵内存,容易出内存越界和泄漏的问题。在类型的转换方面是很多约束,甚至强制转换也要很谨慎,一不小心就出大问题。

优点:弱类型使用简单,更灵活多变。

缺点:因为不包含类型信息,所以在代码的上下文中,可能会进行隐含的类型转换,比如把字符串转整型,整型转字符串,这样会稍损性能,并且可能会不符合程序本意。

数组方法汇总

原生javascript方法

创建数组

//使用 Array 构造函数:
var arr1 = new Array(); //创建一个空数组
var arr2 = new Array(20); // 创建一个包含20项的数组
var arr3 = new Array("lily","lucy","Tom"); // 创建一个包含3个字符串的数组
//使用数组字面量表示法
var colors = [];
var colors = ['red', 'blue'];

检测数组

if(arr instanceof Array) {}
//如果网页中包含多个框架,则需要使用下面的方式检测数组

if(Array.isArray(arr)) {}

arr.valueOf()

var colors = ['red', 'yellow'];
colors.valueOf();
// > ['red', 'yellow']

arr.toString()

var colors = ['red', 'yellow'];
colors.toString();
// > "red,yellow"

join()

join(separator): 将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符。

var arr = [1,2,3];
console.log(arr.join());// 1,2,3
console.log(arr.join("-")); // 1-2-3
console.log(arr); // [1, 2, 3](原数组不变)

arr.push(item)

从数组末尾添加元素,并返回新数组的长度

var colors = ['red', 'yellow'];
colors.push('pink');
// > 3

arr.pop()

从数组末尾删除元素,并返回被删除的元素

var colors = ['red', 'yellow'];
colors.pop();
// > 'yellow'

arr.unshift(item)

从数组头部添加元素,并返回新数组的长度

var colors = ['green', 'pink'];
colors.unshift('pink');
// > 3

arr.shift()

从数组头部删除元素,并返回被删除的元素

var colors = ['yellow', 'orange'];
colors.shift();
// > 'yellow'

arr.reverse()

反转数组的顺序,并返回重新排序之后的数组, 原数组会被改变

[1, 2, 3, 'reer', 'game', 2, 5].reverse();
// > [5, 2, "game", "reer", 3, 2, 1]

arr.sort(fn)

如果不传参数,默认情况下数组内的元素会被转换为字符串进行比较,因此一般不推荐直接使用默认的arr.sort()进行排序。
返回值为排序后的新数组。原数组会被改变

//将数组内数值元素从小到大排序。
var demo = [1, 4, 2, 'reee', 'name', '9', 'doc'];
demo.sort(function(a, b)) {
    return a - b;
}
// > [1, 2, 4, "reee", "name", "9", "doc"]
将数组内数值元素从大到小排序
var demo = [1, 4, 2, 'reee', 'name', '9', 'doc'];
demo.sort(function(a, b) {
    return b - a;
})
// > [4, 2, 1, "reee", "name", "9", "doc"]

arr.concat(otherArr)

参数中传入元素或者数组, 会将该参数合并到arr中,返回合并后新的数组,原数组不会改变

var arr = [1, 3, 'jake'];
arr.concat('rose', [2, 'fi']);
// > [1, 3, 'jake', 'rose', 2, 'fi']

arr.slice()

剪切数组,返回剪切之后的数组,元素不会改变

//传入一个参数,表示起始位置,结束位置为最末尾
var arr = [4, 2, 1, "reee", "name", "9", "doc"];
arr.slice(2);
// > [1, "reee", "name", "9", "doc"]
传入2个参数,表示起始位置与结束位置,但不包括结束位置所在的元素
var arr = [4, 2, 1, "reee", "name", "9", "doc"];
arr.slice(2, 4);
// > [1, "reee"]

arr.splice()

根据参数的不同,可以分别实现删除,插入,替换元素的作用,会改变原始数组

删除

传入2个参数, 分别表示起始位置与要删除元素的个数,返回被删除掉的元素组成的数组
var arr = [4, 2, 1, "reee", "name", "9", "doc"];
arr.splice(2, 3);
// > [1, "reee", "name"]
// arr: [4, 2, "9", "doc"]
插入
传入3个参数, [起始位置 | 要删除的项数 为0 | 要插入的元素], 最终返回删除掉的元素组成的数组,因为这里删除项数为0,因此会返回空数组

var arr = [2, 4, 6];
arr.splice(2, 0, 'red', 'green'); 
// > []
// arr: [2, 4, "red", "green", 6] 
替换
传入三个参数, [ 起始位置 | 要删除的项数 为1 | 要插入的元素 ],最终返回被删除掉的元素组成的数组

var arr = [2, 4, 9];
arr.splice(1, 1, ['tim', 'tom']);
// > [4]
// arr: [2, ['tim', 'tom'], 9]

总结 因此,这个方法会因为参数的不同而实现不同的功能,所有的参数从头到尾依次为
[ 起始位置 | 要删除元素的个数 | 要插入元素的值,可以写入多个值 ]


arr.indexOf(item)

验证数组中是否含有某个元素,返回第一个匹配到的元素在数组中所在的位置,如果没有,则返回 -1

var arr = [2, 'tim', 4, 5, 2];
arr.indexOf('tim');
// > 1
arr.indexOf('jake');
// > -1

arr.lastIndexOf(item)

验证数组中是否含有某个元素,不过是从数组尾部开始查找,返回第一个匹配到的元素所在的位置,如果没有,则返回-1

var arr = [2, 'tim', 4, 5, 2];
arr.lastIndexOf('tim');
// > 1
arr.indexOf('jake');
// > -1
IE6, 7, 8 不支持indexOf与lastIndexOf方法

arr.every()

对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true。会有一个函数作为every的参数,该函数也有3个参数,分别为
[ 调用every的数组的每一项元素 | 对应元素所在的位置 | 表示该数组 ]

var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var everyRes = numbers.every(function(item, index, array) {
    return item > 2;
})
// > false

arr.some()

对数组中的每一项运行给定函数,如果该函数对其中一项返回true,则返回true。会有一个函数作为every的参数,该函数也有3个参数,分别为
[ 调用every的数组的每一项元素 | 对应元素所在的位置 | 表示该数组 ]

var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var everyRes = numbers.some(function(item, index, array) {
    return item > 2;
})
// > true

arr.filter(fn)

过滤方法。返回满足条件的元素组成的数组。fn的参数为
[ 调用every的数组的每一项元素 | 对应元素所在的位置 | 表示该数组 ]

var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var everyRes = numbers.filter(function(item, index, array) {
    return item > 2;
})
// > [ 3, 4, 5, 4, 3 ]

arr.map(fn)

对数组的每一项进行计算等处理,返回处理结果组成的数组,fn的参数为
[ 调用every的数组的每一项元素 | 对应元素所在的位置 | 表示该数组 ]

var numbers = [1, 2, 3, 3, 2, 1];
var everyRes = numbers.map(function(item, index, array) {
    return item > 2;
})
// >[false, false, true, true, false, false]

arr.forEach(fn)

遍历数组,没有返回值,fn的参数为
[ 调用every的数组的每一项元素 | 对应元素所在的位置 | 表示该数组 ]

numbers.forEach(function(item, index) {
    // do something
})

arr.reduce(fn)

缩减方法。fn的参数为[ 前一个元素 | 当前元素,从1开始 | 后一个元素的序列,从1开始计数 | 表示该数组 ]

var values = [1, 2, 3, 4, 5];
var sum = values.reduce(function(prev, cur, index, array) {
    return prev + cur;
})
// > 15 
//每一次迭代之后的结果分别为
// [3, 3, 4, 5]
// [6, 4, 5]
// [10, 5]
// 15

arr.reduceRight(fn)
与reduce一模一样,只是方向相反。

jQuery相关方法

$.each(arr, fn)

遍历数组或者对象,fn有2个参数,分别为, 比原生的for in 更加健壮
[ 数组的索引或者对象的key值 | 索引或者key值对应的value值 ]

var arr = [1, 2, 3];
$.each(arr, function(key, value) {
    // do something
});
跳过一次循环 return | return true
终止循环 return false

$.grep(arr, fn)

过滤方法,功能类同原生中的arr.filter(fn)。此处fn的参数如下
[ value: 对象/数组的值 | key值或者序列 ]

var arr = [ 1, 3, 6, 4 ];
$.grep(arr, function(val, key) {
    return val >= 3;
});
// > [3, 6, 4]
// arr : [ 1, 3, 6, 4 ] 不会改变

$.map(arr, fn)

对每项进行处理,返回处理结果组成的数组,此处fn的参数如下
[ value: 对象/数组的值 | key值或者序列 ]

var arr = [1, 2, 5, 3];
$.map(arr, function(val, key) {
    return val * 10;
})
// > [10, 30, 30, 20, 10]
// 原数组不受影响

$.inArray(item, array)

检测某一个元素item是否存在与数组之中,返回其所在的位置,如果不在,则返回-1

$.inArray(3, [1, 2, 3]);
// > 2

$.merge(arr1, arr2)

合并数组,会改变第一个参数的数组为合并之后的数组,返回合并之后的数组

var arr = [1, 3, 4];
var arr2 = [4, 3, 1];
$.merge(arr, arr2);
// > [1, 3, 4, 4, 3, 1]
// 为了防止第一个数组被改变,可以使用下面的方式来写
$.merge($.merge([], arr), arr2);

$.unique(arr)

过滤DOM数组中重复的元素

$.makeArray(obj)

将类数组对象转换为数组

$(elem).toArray()

将jQuery对象集合恢复成DOM数组

开发微信小程序遇到的问题

开发微信小程序遇到的问题

  1. 编译出错,打开控制台提示:Error:ENOENT:no such file or director,open'c:\目录\game.json'


解决方法:在文本编辑器中打开project.config.json文件,将"compileType": "game",修改为"compileType": "miniprogram",
同样这个"isGameTourist": false,这一项删掉

  1. 微信小程序之报错—pages/welcome/welcome 出现脚本错误或者未正确调用 Page()是什么问题?

解决方法:提示这个 “pages/welcome/welcome 出现脚本错误或者未正确调用 Page()”的最可能的原因是:welcome.js文件是一个空文件。对于空白的js文件,
小程序有时候不会报错,但有时候就会提示这个错误。解决方式是在js文件里加入一个空白的Page函数调用:

      Page({ 
      })
 不要完全是一个空白的js文件放在那里。
  1. 微信小程序报错VM546:2 enablePullDownRefresh 字段需为 boolean

解决方法:某一变量或者方法的类型改变,找到enablePullDownRefresh把 true的双引号去掉,变成boolean类型,项目正常运行,即可解决问题

小技巧

Windows 下使用tree命令生成目录树

tree命令格式:

TREE [drive:][path] [/F] [/A]

/F 显示每个文件夹中文件的名称。使用时显示所有目录及目录下的所有文件,省略时,只显示目录,不显示目录下的文件;
/A 使用 ASCII 字符,而不使用扩展字符。

在 Linux 和 Mac OS 系统中tree命令有更强大的功能,但在Windows下只有 /F /A

使用方法: 在windoc 或powershell 中打开指定文件,输入相关命令,你可以选择在DOS中直接显示,也可以存为txt文件。

tree /f              // 直接显示
tree /f > tree.txt   // 存为txt文件

之后就可以复制其中的内容了如下

└─ToDoList
    ├─ToDoItem
    │  ├─DeleteToDoButton
    │  └─EditToDoButton
    └─ToDoListFooter
        ├─ClearToDoButton
        └─ToDoListStatistics

算法相关--冒泡与快排

算法相关

手写数组快速排序

关于数组快排算法的详细说明,可以参考阮一峰老师的文章快速排序

方法一

"快速排序"的**很简单,整个排序过程只需要三步:
(1)在数据集之中,选择一个元素作为"基准"(pivot)。

(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。

(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

参考代码:

var quickSort = function(arr) {
  if (arr.length <= 1) { return arr; }
  var pivotIndex = Math.floor(arr.length / 2);
  var pivot = arr.splice(pivotIndex, 1)[0];
  var left = [];
  var right = [];
  for (var i = 0; i < arr.length; i++){
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }
  return quickSort(left).concat([pivot], quickSort(right));
};
console.log(quickSort([5,8,5,5,8]));//[5,5,5,8,8]

JavaScript实现二分法查找

二分法查找,也称折半查找,是一种在有序数组中查找特定元素的搜索算法。查找过程可以分为以下步骤:
(1)首先,从有序数组的中间的元素开始搜索,如果该元素正好是目标元素(即要查找的元素),则搜索过程结束,否则进行下一步。
(2)如果目标元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,然后重复第一步的操作。
(3)如果某一步数组为空,则表示找不到目标元素。
参考代码:

// 非递归算法
function binary_search(arr, key) {
    var low = 0,
	high = arr.length - 1;
    while(low <= high){
	var mid = parseInt((high + low) / 2);
	if(key == arr[mid]){
	    return  mid;
	}else if(key > arr[mid]){
	    low = mid + 1;
	}else if(key < arr[mid]){
	    high = mid -1;
	}else{
	    return -1;
	}
    }
};
var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
var result = binary_search(arr,10);
console.log(result); // 9 返回目标元素的索引值       


// 递归算法
function binary_search(arr,low, high, key) {
    if (low > high){
	return -1;
    }
    var mid = parseInt((high + low) / 2);
    if(arr[mid] == key){
	return mid;
    }else if (arr[mid] > key){
	high = mid - 1;
	return binary_search(arr, low, high, key);
    }else if (arr[mid] < key){
	low = mid + 1;
	return binary_search(arr, low, high, key);
    }
};
var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
var result = binary_search(arr, 0, 13, 10);
console.log(result); // 9 返回目标元素的索引值  

利用数组的排序方法sor

var count=0;
function sortNumber(a,b){   //定义排序规则
    console.log(count++);  
    return a-b;
}
console.log(arr.sort(sortNumber));  //数组排序方法sort

冒泡排序(升序): 每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置

function popSort(arr){  
  let length = arr.length;  
  if(length>1){  
    //n个数的数组需要排序(n-1)轮  
    for(let i=0;i<length-1;i++){  
       //每一轮比较的次数逐次递减  
       for(let j=0;j<length-1-i;j++){  
         let a =0;  
         if(arr[j]>arr[j+1]){  
           a =arr[j];   
           arr[j] =arr[j+1];   
           arr[j+1] =a;   
         }  
       }  
    }   
  }  
  return arr;   
}
var arr = [90,0,-10,88,999,100,102,2,3,20];;
console.log(popSort(arr))

归并排序:将数组分为两个子数组,重复此操作直到所有的子数组都只含有一个元素,然后从底部开始两两合并;合并与分割同时进行;

 function mergeSort(arr){  
  let length = arr.length;  
  if(length<=1|| (!Array.isArray(arr))){return arr;}  
  //分割数组  
  let mid = Math.floor(length/2);  
  let left = arr.slice(0,mid);  
  let right = arr.slice(mid);  
  return mergeArr(mergeSort(left),mergeSort(right)) ;  
}  
 //合并数组  
 function mergeArr(left,right){  
 let result =[];  
 while(left.length>0&&right.length>0){  
   if(left[0]<right[0]){  
    result.push(left.shift());  
   }else{  
    result.push(right.shift());  
   }   
  }  
  return result.concat(left,right);  
}  
  
let array1 = [10,2,1,7,12,5,9,0];  
console.log(mergeSort(array1))//返回[0, 1, 2, 5, 7, 9, 10, 12]  

最后对冒泡排序与快速排序两种方法进行对比分析:

  • 以上两种快速排序方法都比上面的冒泡排序的比较次数少,效率高。
  • 冒泡排序简单实用易于理解,而直接使用数组方法则更加简单快捷高效率的解决排序问题.

Web安全

你所了解到的Web攻击技术

(1)XSS(Cross-Site Scripting,跨站脚本攻击):指通过存在安全漏洞的Web网站注册用户的浏览器内运行非法的HTML标签或者JavaScript进行的一种攻击。
(2)SQL注入攻击
(3)CSRF(Cross-Site Request Forgeries,跨站点请求伪造):指攻击者通过设置好的陷阱,强制对已完成的认证用户进行非预期的个人信息或设定信息等某些状态更新。

前端性能

如何优化图像、图像格式的区别?

浏览器是如何渲染页面的?

设计模式:面向对象与面向过程

对MVC、MVVM的理解

正则表达式

写一个function,清除字符串前后的空格。(兼容所有浏览器)

function trim(str) {
    if (str && typeof str === "string") {
        return str.replace(/(^\s*)|(\s*)$/g,""); //去除前后空白符
    }
}

使用正则表达式验证邮箱格式

    var reg = /^(\w)+(\.\w+)*@(\w)+((\.\w{2,3}){1,3})$/;
    var email = "[email protected]";
    console.log(reg.test(email));  // true  

职业规划

对前端工程师这个职位你是怎么样理解的?

a. 前端是最贴近用户的程序员,前端的能力就是能让产品从 90分进化到 100 分,甚至更好

b. 参与项目,快速高质量完成实现效果图,精确到1px;

c. 与团队成员,UI设计,产品经理的沟通;

d. 做好的页面结构,页面重构和用户体验;

e. 处理hack,兼容、写出优美的代码格式;

f. 针对服务器的优化、拥抱最新前端技术。

面试题<三>

面试题

1、快速排序和冒泡排序
2、BFC 概念,BFC 怎样形成的
3、AMD 和 CMD 的概念
4、import 和 export
5、rem 的适配方案
6、git 或 svn 常用命令
7、闭包,构造函数,继承
8、flex 布局和 fle 兼容性问题
9、浏览器从 url 输入到渲染成页面经历了哪些过程
10、ES6 语法
11、grunt 和 gulp 原理及应用
12、本地 localstorage 和 session 的区别
13、nodejs 是干什么用的
14、http https 的概念,为什么 http 不能访问 https
15、npm 包管理机制,package.json
16、html 语义化和 H5 标签
17、页面性能优化
18、前端 SEO
19、IE8 的兼容问题,hack
20、在改变 url 时页面不刷新的办法

请问下这些结果

[]+[] 

[]+{} 

{}+[] 

{}+{}

非 primitive type 的 + 运算,对于数组和 object,其实都是在调用 toString 方法。其中,数组 [] 的 toString 其实就是调用 .join() 方法。
Object 转成 String 就是 '[object Object]' (可以通过 String({}) 测试)
对于 [] + {},相当于 '' + '[object Object]'。
对于 {} + [],引擎会认为 {} 是 code block。所以就是在调用 [].toPrimitive,也就是 [].join()。得到空字符串。然后 +'' 得到 0。
如果写成 ({}) + [] 就是和上面一样的结果了。
对于 {} + {}。有些环境会把它认为是 expression (表达式),所以得到上面的结果。有些环境会得到 NaN。
其实相当于 + '[object Object]'。因此是 NaN

JavaScript 的糟粕

eslint 有哪些规则

移动端开发的时候常见的问题( 1px、点击穿透、点击延迟、三倍图、svg or png 的选择)

框架方面 jq 的基本原理(比如怎么实现的选择器,不用太深)

vue 的常见问题( watch 和 computed 区别)

react 的几个生命周期,组件传值

javascript面试题

  1. 列举 JavaScript 中所有假值

  2. 请写出一个函数initArray,接受两个参数 m 和 n,返回一个数组,它的长度是 m,每个值都是 n

  3. 请写出一个函数yesterday,接受一个 Date 类型参数 date,返回一个 Date,正好是 date 的前一天

  4. 现有二个字段:id,Number 类型; name,String 类型。取值自定义,请写出相应的 json。

  5. 完成extname函数,它会接受一个文件名作为参数,你需要返回它的扩展名。例如,输入emoji.png,返回.png

  6. 请写出以下代码的执行结果

var name = 'World!'; 
(() => { 
if (typeof name === 'undefined') { 
var name = 'Jack'; 
console.log('Goodbye ' + name); 
} else { 
console.log('Hello ' + name); 
} 
})();

HTML ( 2、3 题二选一作答,4、5、6 题三选二作答)

  1. 列举 HTML 中标签常用的全局属性,并描述其作用

  2. 列举 HTML 中常用的块级元素,并描述其作用

  3. 列举 HTML 中常用的行内元素,并描述其作用

  4. 列举 HTML5 中 input 标签的新增 type 属性值,并描述其作用

  5. 列举 form 标签的 method 属性和 enctype 属性值,并描述其作用

  6. 列举 button 标签的 type 属性值,并描述其作用

  7. 定义一个 a 标签,在浏览器新窗口中打开http://www.baidu.com

  8. 列举常用 HTTP 状态码及其含义

css

  1. 有一个div#wrapper元素,高、宽度都未知。它其中有一个宽高都为 100px 的div#box元素,
    请你完成 CSS,使得div#boxdiv#wrapper内水平、垂直方向居中。

  2. 韩梅梅拒绝了李雷,李雷伤心地问韩梅梅,你到底喜欢怎么样的男生。韩梅梅说,她喜欢又高、又富、又帅的男生。
    假设现在页面上有很多个 div 元素代表不同的男生,类名表示他们具有的特性,例如 tall 表示高,wealthy 表示富,
    handsome 表示帅。请你完成 CSS, 给韩梅梅喜欢的男生加上红色的边框( 1px solid red )。

  3. 对 float 的理解

  4. 利用伪元素实现 clear:both 的简单解释

  5. 有几种 CSS Box 和说出实现方案、BFC

有关 CSS 盒模型(CSS BOX MODEL)

用原生JS读写CSS样式的方法总结

原文参考链接:http://www.cnblogs.com/susufufu/p/5749922.html
为了日后方便查询,本人翻阅了一些资料总结了以下方法,仅限原生JS

一、可以通过DOM节点对象的style对象(即CSSStyleDeclaration对象)来读写文档元素的CSS样式

如:

var elm = document.getElementById("test");
elm.style.color = "black";

二、通过Element对象的getAttribute()、setAttribute()、removeAttribute()直接读写style属性

如:

elm.setAttribute('style','color:red;line-height:30px');

三、通过CSSStyleDeclaration对象的cssText属性和setProperty()、removeProperty等方法

如:

elm.style.cssText ='color:red;line-height:30px';
elm.style.removeProperty('color');
elm.style.setProperty('color', 'green', 'important');
elm.style.cssText = '';//快速清空该规则的所有声明

 每一条CSS规则的样式声明部分(大括号内部的部分),都是一个CSSStyleDeclaration对象,它的属性和方法:
  属性:
      1.cssText:当前规则的所有样式声明文本。该属性可读写,即可用来设置当前规则。
      2.length:当前规则包含多少条声明。
      3.parentRule:包含当前规则的那条规则,同CSSRule接口的parentRule属性。
  方法:
      1.getPropertyPriority()方法返回指定声明的优先级,如果有的话,就是“important”,否则就是空字符串;
      2.getPropertyValue方法返回指定声明的值;
      3.item(index)方法返回指定位置的属性名,一般用[index]语法更直接;
      4.removeProperty方法用于删除一条CSS属性,返回被删除的值;
      5.setProperty方法用于设置指定的CSS属性,没有返回值;

四、利用document.styleSheets属性,返回当前页面的所有StyleSheet对象(即所有样式表),它是一个只读的类数组对象,它的元素是CSSStyleSheet对象(继承自StyleSheet对象),该对象的属性方法如下:

    属性:
            1.cssRules类数组对象,元素是样式表中CSS规则CSSStyleRule对象;IE9以下为rules;
            2.disabled属性用于打开或关闭一张样式表,值为true或disabled;
            3.ownerNode属性返回StyleSheet对象所在的DOM节点,通常是<link>或<style>。对于那些由其他样式表引用的样式表,该属性为null;
            4.因为CSS的@import命令允许在样式表中加载其他样式表,就有了parentStyleSheet属性,它返回包括了当前样式表的那张样式表。如果当前样式表是顶层样式表,则该属性返回null;
            5.type属性返回StyleSheet对象的type值,通常是text/css;
            6.title属性返回StyleSheet对象的title值;
            7.href属性是只读属性,返回StyleSheet对象连接的样式表地址。对于内嵌的style节点,该属性等于null;
            8.media属性表示这个样式表是用于屏幕(screen),还是用于打印(print),或两者都适用(all),该属性只读,默认值是screen;
    方法:deleteRule()从样式表中删除一条规则,insertRule()向样式表中插入一条新规则,IE9以下为addRule()、removeRule();
       如:

document.styleSheets[0].insertRule('#test:hover{color: white;}',0);
document.styleSheets[0].deleteRule(0); //删除样式表中的第一条规则
document.styleSheets[0].cssRules[1].selectorText; //返回选择器字符串
document.styleSheets[0].cssRules[1].cssText; //返回规则字符串,含选择器
document.styleSheets[0].cssRules[1].style.border;
document.styleSheets[0].cssRules[1].style.cssText; //返回当前规则的所有样式声明字符串

五、用window对象的getComputedStyle方法,第一个参数是Element对象,第二个参数可以是null、空字符串、伪元素字符串,该方法返回一个_只读_的表示计算样式的CSSStyleDeclaration对象,[它代表了实际应用在指定元素上的最终样式信息,即各种CSS规则叠加后的结果]

如:

var color = window.getComputedStyle(elm, ':before').color;
var color = window.getComputedStyle(elm, ':before').getPropertyValue('color');
或:var color = window.getComputedStyle(elm, null).color;

    表示计算样式的CSSStyleDeclaration对象与表示内联样式的CSSStyleDeclaration对象的区别:
        1.计算样式的属性是只读的;
        2.计算样式的值是绝对值,类似百分比和点之类相对的单位将全部转换为以'px'为后缀的字符串绝对值,其值是颜色的属性将以“rgb(#,#,#)”或“rgba(#,#,#,#)”的格式返回;
        3.不计算复合属性,只基于最基础的属性,如不要查询margin,而单独查询marginTop等;
        4.计算样式对象未定义cssText属性;
        5.计算样式同时具有欺骗性,使用时需注意,在查询某些属性时的返回值不一定精准,如查询font-family;
        6.IE9以下不支持getComputedStyle方法,IE的Element对象有currentStyle属性;

六、直接添加样式表

1.创建标签<style>添加一张内置样式表

var style1 = document.createElement('style');
style1.innerHTML = 'body{color:red}#top:hover{background-color: red;color: white;}';
document.head.appendChild(style1);
var style1 = document.createElement('style');
style1.innerHTML = 'body{color:red}#top:hover{background-color: red;color: white;}';**
document.head.appendChild(style1);

2.另一种是添加外部样式表,即在文档中添加一个link节点,然后将href属性指向外部样式表的URL

var link1 = document.createElement('link');
link1.setAttribute('rel', 'stylesheet');
link1.setAttribute('type', 'text/css');
link1.setAttribute('href', 'reset-min.css');
document.head.appendChild(link1);

七、window.matchMedia方法用来检查CSS的mediaQuery语句。各种浏览器的最新版本(包括IE 10+)都支持该方法,对于不支持该方法的老式浏览器,可以使用第三方函数库matchMedia.js;

        下面是mediaQuery语句的一个例子:
            @media all and (max-device-width: 700px) {
                  body {background: #FF0;}
            }
    window.matchMedia方法接受一个mediaQuery语句的字符串作为参数,返回一个MediaQueryList对象。该对象有以下两个属性:
    media:返回所查询的mediaQuery语句字符串。
    matches:返回一个布尔值,表示当前环境是否匹配查询语句。
            var result = window.matchMedia('(max-width: 700px)');
            if (result.matches) {
                  console.log('页面宽度小于等于700px');
            } else {
                  console.log('页面宽度大于700px');

            }
    window.matchMedia方法返回的MediaQueryList对象有两个方法,用来监听事件:addListener方法和removeListener方法。如果mediaQuery查询结果发生变化,就调用指定的回调函数;

            var mql =  window.matchMedia("(max-width: 700px)");
            mql.addListener(mqCallback);// 指定回调函数
            mql.removeListener(mqCallback);// 撤销回调函数
            function mqCallback(mql) {
                  if (mql.matches) {// 宽度小于等于700像素} 
                  else { // 宽度大于700像素}
            }

参考链接:
MDN: https://developer.mozilla.org/zh-CN/docs/Web/API
阮一峰javascript参考:http://javascript.ruanyifeng.com/dom/css.html
javascript权威指南第六版

js数据类型

javascript数据类型(1~6是基本(原始)类型,7是引用类型):

1.number;

2.string;

3.boolean;

4.undefined;

5.null;

6.symbol(ES6新增,文章后面有对着新类型的解释)

7.Object.(包括Object,Array,Function)

var arry=[1,2,3];
var nul=null;
console.log(typeof arry);//object
console.log(typeof nul );//object

事实上(函数对象,普通对象)以及(基本数据类型,引用数据类型)是在不同角度对js变量进行的定义

思考1: js的引用数据类型都属于函数对象吗?

引用类型值:指的是那些保存在堆内存中的对象,意思是,变量中保存的实际上只是一个指针,这个指针执行内存中的另一个位置,由该位置保存对象


那么数组,普通对象,函数对象都算是引用数据类型,引用数据类型范围包含函数对象的范围

思考2:js有五种基本类型:Undefined,Null,Boolean,Number和String,他们都是属于普通对象吗?

基本类型值:指的是保存在栈内存中的简单数据段;除开函数对象之外的对象都是普通对象,那么普通对象范围是包含基本数据类型的

Null类型

另一种只有一个值(值为null)的类型是 Null,它只有一个专用值 null,即它的字面量。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。

alert(null == undefined);  //输出 "true"

尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象。如果函数或方法要返回的是对象,
那么找不到该对象时,返回的通常是 null。

那么就有当声明一个变量,这个变量的值为null,那么这个变量就是“不存在的”

基本类型和引用类型的区别

  1. 基本类型: string,number,boolean,null,undefined,symbol
  2. 引用类型: Function,Array,Object

区别

访问方式:基本类型:操作和保存在变量的实际的值

引用类型: 值保存在内存中,js不允许直接访问内存,在操作的时候,操作的是对象的引用

存储的位置:基本类型: 保存在栈中

引用类型: 引用存放在栈区,实际对象保存在堆区

由上图可以看出当声明了一个引用变量,在堆内存中就有了一个专属的位置,除非是复制的,否则不可能相等,有以下代码为证:

console.log({}=={});//false
console.log([]==[]);//false

symbol类型

   var a2 = Symbol('a')
    a1 !== a2 // true

每个从Symbol()返回的symbol值都是唯一的。一个symbol值能作为对象属性的标识符;这是该数据类型仅有的目的

Symbol 生成一个全局唯一的值。
MDN上关于symbol的解释

instanceof与typeof,prototype与_proto_

instanceof与typeof

typeof 
operand

operand 是一个表达式,表示对象或原始值,其类型将被返回

object instanceof constructor

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上

instanceof 运算符 判断的对象一般有:Array Function Object 等引用类型的实例对象

// 定义构造函数

function C(){} 
function D(){} 

var o = new C();

// true,因为 Object.getPrototypeOf(o) === C.prototype

o instanceof C; 

// false,因为 D.prototype不在o的原型链上

o instanceof D; 

o instanceof Object; 
// true,因为Object.prototype.isPrototypeOf(o)返回true

C.prototype instanceof Object 
// true,同上

C.prototype = {};
var o2 = new C();

o2 instanceof C; 
// true

o instanceof C; 
// false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.

D.prototype = new C(); 
// 继承

var o3 = new D();
o3 instanceof D; 
// true

o3 instanceof C; 
// true

需要注意的是,如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回true,因为Foo.prototype属性的值有可能会改变,
改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false。另外一种情况下,原表达式的值也会改变,就是改变对象obj的原型链的情况,
虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的__proto__魔法属性,是可以实现的。比如执行obj.proto = {}之后,
obj instanceof Foo就会返回false了。

写一个方法判断数据类型::
function judType(vars){
if(vars===null)  return 'null'; 
else if(typeof vars!='object')   return typeof vars;
else{
if(vars instanceof Array){
return 'Array';
}
if(vars instanceof Function){
return 'Function';
}
else if(vars instanceof Object)return 'object';
    }
}
var a=1;
var b="22";
var c=true;
var d;
var e=null;
var g={a:a};
var h=[1,2,3];
var i=function(){};

console.log(judType(a));
console.log(judType(b));
console.log(judType(c));
console.log(judType(d));
console.log(judType(e));
console.log(judType(g));
console.log(judType(h));
console.log(judType(i));

console.log(null==undefined);//true
console.log(null===undefined);//false

prototype与_proto_

prototype 是原型,是Function对象才有的属性(如果你不信,你尽可尝试其他的数据类型,得到的绝对是undefined),原型主要是用来实现继承,从而用js 进行面向对象编程;

	var person=function(){
				this.name="animal";
			};
	var p=new person();
	console.log(person.prototype);//object Object
	console.log(p.prototype);//undefined

因为构造函数的实例对象没有prototype,于是有_proto_

所有对象的_proto_都指向其构造函数的prototype,而构造函数的_proto_则都指向Function.prototype,一个空函数(Empty function)

var person=function(){ 
	this.name="animal"; 			
}; 			
var p=new person(); 			 			
console.log(person.prototype);//object Objec 			
console.log(person.__proto__);//function Empty() {}  			
console.log(p.prototype);//undefined 			
console.log(p.__proto__);//object Objec 			 			
console.log(person.prototype==p.__proto__);//true 	
//可见,实例指向函数实例对象的_proto_ 指向  函数的原型prototype;
var man=function (){} 				
man.prototype=new person();//子类原型链继承父类 
var littleman=new man(); 			 				
console.log(littleman.name);//animal 	
console.log(man.prototype);//[object Object] 				
console.log(man.__proto__);//function Empty() {} 
console.log(littleman.prototype);//undefined 				
console.log(littleman.__proto__);//[object Object] 	

原型链作为实现继承的主要方法。其基本**是利用原型让一个引用类型继承另一个引用类型的属性和方法。

在JavaScript中,用_proto_ 属性来表示一个对象的原型链。当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止!

原型链继承方法 参考博文 彻底深刻理解js原型链之prototype,__proto__以及constructor(一)

注意:prototype与_proto_是属性,typeof是操作符,instanceof是运算符

javascript 知识整理二

javascript 知识整理二

说说this几种不同的使用场景

var a = {
	name:'A',
	fn: function(){
	    console.log(this.name)
	}
}
a.fn() //A  this=== a

a.fn.call({name:'B'}) // B  this ==={name: 'B'}

var fn1 = a.fn
fn1() // this === window

作为构造函数执行 (this 指向创建出来的实例对象)

function Foo(name) {
    this.name = name
}
var f = new Foo('年糕');
console.log(f.name)// 年糕

作为对象属性执行 (this 指向调用该方法的对象)

var obj = {
    name: 'Niangao',
    printName: function() {
        console.log(this.name)
    }
}
obj.printName() //Niangao

作为普通函数执行 (this 指向 window)

function fn() {
    console.log(this)
}
fn() // window

call() 方法 apply() 方法 bind() 方法 (this 指向第一个参数)

function fn1(name, age) {
    console.log(name)
    console.log(this)
}
fn1.call({x:100}, 'niangao', 17) // niangao {x:100}

function fn2(name, age) {
    console.log(name)
    console.log(this)
}
fn2.apply({x:100}, ['niangao', 17]) //niangao {x:100}

var fn3 = function(name){
    console.log(name)
    console.log(this)
}.bind({y:200})
fn3('niangao') // niangao {y:200}

闭包在实际开发中的应用

闭包实际应用中主要用于封装变量,收敛权限,下面是一个验证是否为第一次登陆的例子

function ifFirstLoad() {
    var _list = [];
    return function (id) {
        if(_list.indexOf(id) >= 0) {
            return false;
        }else {
            _list.push(id);
            return true;
        }
    }
}
var firLoad =ifFirstLoad();
firLoad(10);//true
firLoad(10);//false
firLoad(20);//true

闭包的使用场景主要有两个:① 函数作为返回值;② 函数作为参数传递

function F1() {
    var a = 100;
    // 函数作为返回值
    return function(){
        console.log(a)
    }
}
var f1 = F1();

function F2(fn) {
    var a = 200;
    // 函数作为参数传递
    fn()
}
F2(f1)

创建 10 个 标签,点击的时候弹出对应的序号

for(var i = 0; i < 10; i++){
    (function(i){
        var div = document.createElement('div');
        div.innerHTML = i + '<br>';
        div.addEventListener('click', function(e){
            e.preventDefault();
            console.log(i);
        })
        document.body.appendChild(div)
    })(i)
}


如何理解作用域

① 没有块级作用域,只有函数和全局作用域
② 自由变量
③ 作用域链,即自由变量的查找

// 无块级作用域
if(true){
    var name = "niangao"
}
console.log(name) // niangao

// 函数和全局作用域
var a = 100;
function fn() {
    var a = 200;
    console.log('fn', a);
}
console.log('global', a) // global 100
fn() // fn 200

a 和 b 是自由变量——当前作用域没有定义的变量,即“自由变量”

var a =100;
function F1(){
   var b =200;
   function F2(){
	var c =300;
	console.log(a)
	console.log(b)
	console.log(c)
   }
   F2();
}
F1();
// 100 
// 200 
// 300

上个例子console.log(a); 并没有在当前作用域寻找到自由变量 a,于是不断的往父级作用域寻找自由变量 a,直到全局作用域,
而能够沿着作用域一级级向上寻找的机制就称为“作用域链”

需要注意的是,一个函数的父级作用域是它定义时的作用域,而不是它执行时的作用域

function F1(){
   var a =100;
   return function (){
	console.log(a)
   }
   var f1 =F1();
   var a =200;
   f1();//100

同步和异步的区别是什么

同步会阻塞代码执行,而异步不会

//异步
console.log(100);
setTimeout(function(){
    console.log(200);
}, 1000)
console.log(300);

//同步
console.log(100);
alert(200);
console.log(300);


前端使用异步的场景有哪些

在可能发生等待的情况下,我们会需要异步,比如定时任务(setTimeout, setInterval),网络请求(Ajax 请求,
动态 加载),事件绑定

加载

console.log('start');
var img = document.createElement('img');
img.onload = function(){
    console.log('loaded')
}
img.src = 'https://github.com/Niangao-Warren/JianShu/blob/master/Demo/Mouse_sliding_picture_showing_hidden/images/n1.jpg?raw=true';
console.log('end');
// start
// end
// loaded

一道关于 SetTimeout 的题目

 console.log(1);
setTimeout(function(){
    console.log(2)
}, 0);
console.log(3);
setTimeout(function(){
    console.log(4)
}, 1000);
console.log(5);
// 1
// 3
// 5
// undefined
// 2
// 4

获取 2018-03-23 格式的日期

常用的API:
Date.now() // 获取当前时间毫秒数
var today = new Date()
today.getTime() // 获取毫秒数
today.getFullYear() // 年
today.getMonth() // 月(0-11)
toddy.getDate() // 日(0-31)
today.getHours() // 时(0-23)
today.getMinutes() // 分(0-59)
today.getSeconds() // 秒(0-59)

function formatDate(today) {
    if(!today) {
        today = new Date()
    }
    var year  = today.getFullYear(),
        month = today.getMonth() + 1,
        date  = today.getDate();
    if(month < 10) {
        month = '0' + month;
    }
    if(date < 10) {
        date = '0' + date;
    }
    return year + '-' + month + '-' + date;
}
	var today =new Date();
	var formatDate =formatDate(today)
	console.log(formatDate);
	// 2018-03-23

获取随机数,要求是长度一致的字符串格式

var random = Math.random();
var random = random + '0000000000' // 后面加上 10 个零
var random = random.slice(0, 10);
console.log(random);

写一个能遍历对象和数组的通用 forEach 函数

常用的数组 API 有
API	作用
forEach	遍历所有元素
every	判断所有元素是否都符合条件
some	判断是否有至少一个元素符合条件
sort	排序
map	对元素重新组装,生成新数组
filter	过滤符合条件的元素

forEach 遍历所有元素

item 对应的是元素的值,index 对应的是元素的位置

var arr=[1,2,3];
arr.forEach(function(item,index){
	console.log(index,item)
})
// 0 1
// 1 2
// 2 3

every 用来判断数组所有元素,都满足一个条件

var arr=[1,2,3];
var result =arr.every(function(item,index){
	if(item<4){
		return true;
	}
})
console.log(result)// ture

some 用来判断数组所有元素,只要有一个满足条件即可

var arr=[1,2,3];
var result =arr.some(function(item,index){
	if(item<2){
		return true;
	}
})
console.log(result)// ture

sort 排序

var arr=[1,5,4,2,3];
arr1=arr.sort(function(a,b){
	return a-b;
})
console.log(arr1)
//[1,2,3,4,5]
var arr=[1,5,4,2,3];
arr1=arr.sort(function(a,b){
	return b-a;
})
console.log(arr1)
//[5,4,3,2,1]

map 对元素重新组装,生成新数组

var arr=[1,2,3,4];
arr1=arr.map(function(item,index){
	return item;
})
console.log(arr1)//[1,2, 3, 4]

filter 通过某一条件过滤数组

var arr=[1,2,3,4];
arr1=arr.filter(function(item,index){
	if(item>=2){
	return true;
	}
})
console.log(arr1)//[2, 3, 4]
function forEach(obj, fn) {
    var key;
    if(obj instanceof Array) {
        obj.forEach(function(item, index) {
            fn(index, item)
        })
    }else {
        for(key in obj) {
            fn(key, obj[key])
        }
    }
}
var arr =[1,2,3]
forEach(arr, function(index,item){
console.log(index,item);})
// 0 1
// 1 2
// 2 3
var obj={x:200, y:300}
forEach(obj, function(key,value){
console.log(key,value);
})
// x 200
// y 300

JavaScript 常见面试题分析(二)

数组去重

数组去重

原理

  1. 在ES6之前数组去重的方法原理是:通过新建一个空的数组,通过 indexOf 方法进行新数组和原数组的子元素比较,来得到一个没有重复子元素的新数组
function unique(Arr){
    var arr = [];
    for(var i = 0; i < Arr.length; i++) {
       if(arr.indexOf(Arr[i])==-1) {
           arr.push(Arr[i]);
       }
    }
    return arr;
 }

运行结果
2. ES6 中,新增的 Set() 对象和 Array.from() 方法,可以让我们通过两行代码,就能实现数组去重

var arr = [1,5,1,2,2,6];
var Arr = Array.from(new Set(arr));
/*Set 对象允许你存储任何类型的唯一值,而 Set 中的值总是唯一的,
所以会判断两个值是否相等,Set 返回的是对象,我们还需要通过 Array.from() 方法,
在一个类数组或可迭代对象中,创建一个新的数组实例*/

运行结果
Set 对象允许你存储任何类型的唯一值 ,无论是原始值或者是对象引用

Array.from() 方法从一个类似数组或可迭代的对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等) 中创建一个新的数组实例

说说程序员的核心能力

今天不写摘抄博客了,看了下Phodal大神的文章,我接触前端也是看他的文章认识的,虽然现在没找到合适的工作,但是看看文章,了解自己所在领域的知识还是所获非浅的。

什么是程序员的核心能力?

  • 快速学习
  • 索引知识
  • 解决问题
  • 沟通表达

快速学习

这段时间面试的时候提到面试JD要熟悉某个框架,具体在那个业务上要用到某些技术栈,
如果是新手来说,接触的时间又不长,开始的ES5,jquery,javascript已经让我们脑袋头痛,
还有一些后端的知识,快速上手确实是有难度。但要吃饭,工作该学的还是必须要学,但
可以选一个框架当作主要的学习来提高能力,后面接触工作熟悉后触类旁通,可以慢慢来。

那什么 是快速学习呢?
快速学习是基本的核心能力啊。它所指的,并非是我们能快速使用一个新的框架,而是我们能快速的使用一个新的框架来完成工作。因为当我们谈及快速学习的时候吧,我们多数是在以任务为驱动的学习。

解决问题

慢慢的,当我们习惯了堆砌的代码,就会发现工作中的高潮,就是解决一个个的疑难杂症。解决问题吧,无非就是: 先识别问题,再去解决问题(PS:很是奇怪)。

识别问题。通过复现、Debug 找到出现问题的地方,然后再找寻到出现问题的地方,再去追根溯底。这一步往往是最难的地方,为此,你需要掌握好各式各样的调试工具,前端开发中的 Chrome 调试,后台开发中的实时 Debug、日志记录,移动开发中的抓包工具。还要去了解各个系统的组成,如典型的编码问题,一般都不是应用程序的问题。因此,你要从 Chrome 发出的请求开发,再查看 HTTP 服务器(如 Nginx)接收到的请求,随后便是应用容器(如 Tomcat)转的语法,最后才到应用程序的地方。

解决问题。多数时候,我们所要解决的问题,都是别人遇到的。因此,解决问题的第一原则是使用搜索,多数时候只需要搜索错误提示,就能找到答案。而为了使用好搜索,你还需要找到合适的上网方式。

在解决问题的过程中,最重要的不是解决问题本身,而是诸如问题有没有解、有没有解决问题的必要(即最优解)。如你做了一个混合应用,那么性能问题接近于『无解』。而如果你们的应用不会有性能问题,那么就没有理由去重写应用,以解决性能问题。

索引知识

上手一个新的领域,由于时间精力有限,总会找个人资料、找本书了解、找相关资料探索,随后再找一个 Awesome List,在这个列表里,找到这个领域的一些流行趋势。一步步探索的过程中,我们便在不断地构建这个领域的索引,慢慢地便能识别相关的问题。

因而,当你觉得你对这个领域很了解时,实际上是因为你有了这个领域的索引

沟通表达

作为一个程序员的日常沟通,大概就是业务人员和程序员吧,沟通的要点吧,便是知道对方要表达的东西,再表达清楚自己心里的想法

可作为一个普通的人,是得多和人打交通。与大多数程序员相比吧,在我司还是不错的,至少你要不断地和人沟通,日常的聊天、与客户的沟通、与开发人员的沟通等等。

做一个自己的产品

造轮子、写博客、做 APP,总能让我看到代码之外的,不一样的东西。用某句高大上的话来说,就是看到世界的运行法则。
人生的意义是什么,刚出来工作的时候我也花心思琢磨好久,如果对人生没有实现价值,那活着如何证明我们的存在?

给上链接说说程序员的核心能力:第一个三年:后台、前端、移动应用,第二个三年呢?

JS 常用函数和简单算法

反转字符串

如:hello -> olleh

function reverseString(str) {
  str = str.split('').reverse().join('');
  return str;
}

reverseString("hello");

注意两个''代表空字符串,不能丢

计算阶乘

如:5! = 1 * 2 * 3 * 4 * 5 = 120

function factorialize(num) {
    if(num <= 1) {
        return 1;
    } else {
        return num * factorialize(num - 1);
    }
}

factorialize(5);

这样写比较消耗资源,还可以使用尾递归进行优化

检查是否为回文

如:'eye' -> true, 'Zz' -> true, 'race car' -> true, 'never odd or even' -> true, 0_0 (: /-\ :) 0-0 -> true, gua~ -> false

function palindrome(str) {
  // 统一为小写,除去空格、逗号、句号
  str = str.toLowerCase().replace(/[ |\,|\.|\_|\-|\(|\)]/g,'');
  // 反转
  var rts = str.split('').reverse().join('');

  return str==rts?true:false;
}

palindrome("never odd or even");

这里主要是一个正则表达式,需要把空格,逗号,句号等标点去掉

找出一段文字中的最长单词,返回该单词长度

如:'What is the average airspeed velocity of an unladen swallow' -> 8

function findLongestWord(str) {
  return str
    .split(' ')
    .sort(function(a,b){return a.length-b.length;})
    .pop().length;
}

findLongestWord("What is the average airspeed velocity of an unladen swallow");
  • sort()默认会将数字转换为字符串进行比较,如果需要定制排序方法,可以给 sort() 自定义一个比较函数,这个函数返回值为负数,顺序不变,反之交换位置。
    《JS 语言精粹》讲到这里时有更多例子,包括怎样排序包含数字、文字等的复杂列表 etc.

  • pop()返回Array()最右端的元素.

有二维数组,返回每个子数组中的最大数字

如 :[[4, 9, 1, 3], [13, 35, 18, 26], [32, 35, 97, 39], [1000000, 1001, 857, 1]] -> [9, 35, 97, 1000000]

function largestOfFour(arr) {
  var newArr=[];
  for(var i=0;i<=3;i++){
    newArr[i]=arr[i]
      .sort(function(a,b){return a-b;})	// 数字升序排序
      .pop();
  }
  return newArr;
}

largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);

sort()在这里有个小坑,在进行数字比较的时候,会提前将数字转化为字符串,然后进行比较,所以会出现1001<857的情况。我们需要做的跟上一篇中找最长单词类似
,就是给sort()指定比较方法

给定一个语句和一个单词,检查语句末尾是否为该单词

("What's your name","name") -> ture;("I'm fine","bad" -> false)

function confirmEnding(str, target) {
  // "Never give up and good luck will find you."
  // -- Falcor
  var len = target.length;
  return str.substr(-len) == target?true:false;
}

confirmEnding("Bastian", "n");

substr()方法返回字符串中从指定位置开始到指定长度的子字符串。

str.substr(start[, length])
start 为负数时,从右边第start个字符位置开始,即从str.length+start开始

重复一个字符串n次

如:('abc',3) -> 'abcabcabc

function repeatStringNumTimes(str, num) {
  // repeat after me
  var newStr='';
	for(var i=0;i<num;i++){
    newStr += str;
  }
  return newStr;
}

repeatStringNumTimes("abc", 3);

给定一段文字,从头截取一定长度的字符串

要求:文字长度小于3,或者小于需要截取的字符长度时,略去...;否则加上省略号,并且省略号本身也计算进截取字符串的长度中。

如:("Peter Piper picked a peck of pickled peppers", 14) -> Peter Piper...;

function truncateString(str, num) {
  // Clear out that junk in your trunk
  var len = str.length;
  var newStr = '';
  if(num<=3){
    if(len<=num){
      return str;
    }else{
      return str.slice(0,num) + '...';
    }
  }else{
    if(len<=num){
      return str;
    }else{
      return str.slice(0,num-3) + '...';
    }
  }
}

truncateString("A-tisket a-tasket A green and yellow basket", 11);

slice()方法复制string的一部分构成新的字符串。

语法

slice(start, end), end 在这题里为 num 或者 num - 3

将一维数组转换为二维数组,每个子数组的长度为给定长度(最后一个子数组长度不确定)

如:(["a", "b", "c", "d"], 2) -> [["a", "b"], ["c", "d"]]

function chunkArrayInGroups(arr, size) {
  // Break it up.
  var newArr = [];
  for(var i=0;i<arr.length;i+=size){
    var subArr = arr.slice(i,i+size);
    newArr.push(subArr);
  }
  return newArr;
}

chunkArrayInGroups(["a", "b", "c", "d"], 2);

给定数组,删除前n位,并返回删除后的新数组

如:([1, 2, 3], 2) -> [3]

function slasher(arr, howMany) {
  // it doesn't always pay to be first
  arr.splice(arr,howMany);
  return arr;
}

slasher([1, 2, 3], 2);

Array.splice()方法从Array中移除一个或多个元素,并用新的item替换它们

给定一段文字str1和一个短语str2,检查str2是否为str1的子集(忽略大小写和字符顺序)

如:["hello", "hey"] -> false;["Alien", "line"] -> true

function mutation(arr) {
  var m = arr[0].toLowerCase();
  var n = arr[1].toLowerCase();
  for(var i=0;i<n.length;i++){
    if(m.indexOf(n[i])==-1){return false;}
  }
  return true;
}

mutation(["hello", "Hello"]);

String.indexOf()方法返回指定值在字符串对象中首次出现的位置。从 fromIndex 位置开始查找,如果不存在,则返回 -1。

str.indexOf(searchValue[, fromIndex])

过滤数组中可以表示false的值

可判断为false的值有:false, null, 0, “”, undefined, and NaN

function bouncer(arr) {
  // Don't show a false ID to this bouncer.
  function isFalsy(el){
    return Boolean(el) !== false;
  }

  return arr.filter(isFalsy);
}

bouncer([7, "ate", "", false, 9]);

Array.filter()方法使用一个指定的过滤函数,检测Array中的所有元素,并返回一个全部符合过滤条件的新数组。

总结多读书,多写代码,高程,语言精粹

记一道关于 AJAX 的前端面试题

记一道关于 AJAX 的前端面试题

原文:前端面试时总让写原生Ajax真的很有意义吗?

大致思路:

1. 原生 XHR 怎么写?

1.1 XMLHttpRequest 基础
最简单的,先用 XHR 发起一个 GET 请求为例,这个 GET 请求从服务器获取一个文本文件 example.txt, 并将其文本内容用提示框显示出来:

var xhr = new XMLHttpRequest(); //创建XHR对象
xhr.onreadystatechange = handleResponse; //定义(指定)回调处理函数
xhr.open("get", "example.txt", true); //初始化异步 XHR 请求(此时请求尚未发出)
xhr.send(null);//发出 XHR 请求,至此请求已经发出,浏览器等待服务器的响应

var handleResponse = function(){
	if (xhr.readyState == 4){
		if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
			alert(xhr.responseText);
		} else {
			alert("Request was unsuccessful: " + xhr.status);
		}
	}
};

onreadystatechange 的回调函数在每次 readystate 发生变化时,都会调用 handleResponse 函数。

值	描述
0	未初始化。尚未调用 open()方法。
1	启动。已经调用 open()方法,但尚未调用 send()方法。
2	发送。已经调用 send()方法,但尚未接收到响应
3	接收。已经接收到部分响应数据。
4	完成。已经接收到全部响应数据,而且已经可以在客户端使用了

open() 接受三个参数:请求的类型(”get”、”post”等)、请求资源的 URL 和表示是否异步发送请求的布尔值。

send() 方法的参数是请求主体要发送的数据,如果不需要发送数据,则必须传入 null,因为这个参数对有些浏览器是必需的。

function handleResponse(){...} 服务器响应回调函数

当收到服务器的响应后,响应的数据会自动填充 XHR 对象的属性。

  • responseText:作为响应主体被返回的文本。
  • responseXML:如果响应的内容类型是”text/xml”或”application/xml”,这个属性中将保存包含着响应数据的 XML DOM 文档。对非 XML 数据而言,此属性值为 null
  • status:响应的 HTTP 状态,详见本文第3点。
  • statusText:HTTP 状态的说明。

此时 handleResponse() 函数将判断 readystate 是否为4(响应数据接收完毕),且 http status 是否为 200(表示成功返回)或者
304(表示服务器数据未更改,继续使用浏览器缓存),判断为是后,将对返回结果进行处理。

1.2 更多的 XMLHttpRequest (Level2)

记一道关于-AJAX-的前端面试题
XMLHttpRequest Level 2 使用指南

1.3 get与post的区别

参考 HTTP 方法:GET 对比 POST


2. 怎么处理回调?

  • 请求是否完成(readystate = 4)

  • 返回数据是否正确(status >=200 && status<300 || status = 304)

  • 对返回数据进行处理(alert(xhr.responseText)…)


3. 常见 status 响应状态码?

200 OK 请求成功,此时 responseText 的内容已经就绪。
204 No Content 该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分。另外,也不允许返回任何实体的主体
301 Moved Permanently 永久性重定向。该状态码表示请求的资源已被分配了新的URI,以
后应使用资源现在所指的URI。
302 Found 临时性重定向。该状态码表示请求的资源已被分配了新的URI,希
望用户(本次)能使用新的URI 访问。
304 See Other 请求资源尚未被修改,浏览器可以继续使用缓存中的数据。
401 401 Unauthorized 发送的请求需要有通过HTTP 认证(BASIC 认证、
DIGEST 认证)的认证信息。
403 Forbidden 明对请求资源的访问被服务器拒绝
404 无法找到请求的资源 || 服务器端拒绝请求且不想说明理由
500 Internal Server Error
503 Service Unavailable 超负载或正在进行停机维护
        原因	                                 含义
1XX	Informational(信息性状态码)	接收的请求正在处理
2XX	Success(成功状态码)	请求正常处理完毕
3XX	Redirection(重定向状态码)	需要进行附加操作以完成请求
4XX	Client Error(客户端错误状态码)	服务器无法处理请求
5XX	Server Error(服务器错误状态码)	服务器处理请求出错

HTTP 常见请求方法

方法	描述
GET	从服务器获取资源
POST	向服务器提交要被处理的数据
HEAD	与 GET 相同,但只返回 HTTP 报头,不返回文档主体。
PUT	上传指定的 URI 表示。
DELETE	删除指定资源。
OPTIONS	返回服务器支持的 HTTP 方法。
CONNECT	把请求连接转换到透明的 TCP/IP 通道。

什么是同源策略(Same-Origin Policy)?

同协议,同域名,同端口。

不同源的客户端脚本在没明确授权的情况下,不能读写对方的资源。同源策略可以防止 Cookie 劫持等安全问题。


如何发起跨域请求?

常见的跨域请求方法有:CORS、JSONP、postMessage等,下面分别讲一下,重点是CORS和JSONP

CORS(Cross-Origin Resource Sharing,跨源资源共享):

var xdr = new XDomainRequest(); // IE8+
xdr.onload = function(){
	alert(xdr.responseText);
};
xdr.open("get", "http://www.somewhere-else.com/page/");
xdr.send(null);

其他浏览器对CORS的实现:仅支持IE8以上

要请求位于另一个域中的资源,使用标准的 XHR 对象并在 open()方法中传入绝对 URL:

xhr.open("GET", "https://api.github.com/user",true);

在 HTTP 请求头部加入额外的Origin信息:
Origin: http://sstruct.github.io/

此外,还需要设置服务器Access-Control-Allow-Origin 头部回发相同的源信息(如果是公共资源,可以回发”*”)。例如:

Access-Control-Allow-Origin: http://sstruct.github.io/

JSONP(JSON with padding,填充式 JSON 或参数式 JSON)

JSONP 和 JSON 差不多,只不过是被当作函数参数的 JSON:

function handleResponse(response){
	alert("You’re at IP address " + response.ip + ", which is in " +
		response.city + ", " + response.region_name);
}
var script = document.createElement("script");
script.src = "http://freegeoip.net/json/?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);

参见:《JavaScript 高级程序设计》P587

JSONP 的缺点也要讲一下,首先,JSONP 是从其他域中加载代码执行。如果其他域不安全,很可能会在响应中夹带一些恶意代码。其次,难以确定 JSONP 请求是否失败。

postMessage
HTML5 新增方法(IE8+),语法:

otherWindow.postMessage(message, targetOrigin);

聊聊 Cookie 等浏览器缓存方面

这部分可以看详说 Cookie, LocalStorage 与 SessionStorage - 咀嚼之味, 总结的很好,

Cookie 本身可以通过 document.cookie 设置,这里补充一下 Cookie 的缺点:

  • 只能存储4kb左右
  • 每次会随着http请求带给服务器
  • 安全性问题(存储的数据是明文的, 不要存储密码等数据)
  • 为了提高安全性,可以添加 secure 属性,只在 https 等安全情况下才发送 Cookie

前端安全 CSRF, XSS

XSS(Cross-Site Scripting,跨站点脚本)

XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,
提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。

CSRF(Cross-Site Request Forgery,跨站点请求伪造)

CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端
Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,
让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。

参考 总结 XSS 与 CSRF 两种跨站攻击 - 无知的 TonySeek

关于BFC

详细可参考:前端精选文摘:BFC 神奇背后的原理

BFC是什么?

BFC(Block Formatting Contexts),中文译指:块级格式化上下文。首先我们拆分一下先介绍Box、Formatting Context的概念。

Box: CSS布局的基本单位

box是css布局的对象和基本单位,一个页面由很多个box组成,元素的类型和dispaly属性,决定了这个box的类型。不同类型的box,会参与不同的Formatting Context(一个决定如何绚烂文档的容器),因此box内的元素会以不同的方式渲染。

Formatting context

Formatting context是w3c css2.1规范的一个概念。它是页面中一块渲染区域,并且有一套渲染规则,它决定了其子元素如何将如何定位,以及和其他元素的关系和相互作用,最常见的是 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。
CSS2.1 中只有 BFC 和 IFC, CSS3 中还增加了 GFC 和 FFC。

BFC定义

BFC是一个名词,是一个独立的布局环境,我们可以理解为一个箱子(实际上是看不见摸不着的),箱子里面物品的摆放是不受外界的影响的。并且,在一个BFC中,块盒与行盒(行盒由一行中所有的内联元素所组成)都会垂直的沿着其父元素的边框排列。

BFC的布局规则

1.内部的box会在垂直方向,一个接一个地放置位置。
2.Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的垂直方向的margin会重叠。
3.每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
4.BFC的区域不会与float box 重叠。
5.BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反义也如此。
6.计算BFC的高度时,浮动元素也参与计算

如何生成BFC?

满足下满的条件的任何一点,都会生成BFC

  • 根元素(整个页面就是一个大的BFC);

  • float属性不为none;

  • display为inline-block, table-cell, table-caption, flex, inline-flex

  • position为absolute或fixed;

  • overflow不为visible;

BFC有什么作用?

1.自适应两栏布局
2.清除内部浮动
3.防止垂直的margin重叠

总结

以上的例子都体现了BFC的第五条

BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

因为BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。

javascript知识 总结一

详细的参考JavaScript 常见面试题分析(一)

变量类型及计算:

  1. JS中用 typeof 得到那些数据类型
typeof undefined     // undefined
typeof '123'         // string
typeof 123           // number
typeof true          // boolean
typeof {}            // object
typeof []            // object
typeof null          // object
typeof console.log() //function

typeof 只能区分值类型

  1. 何时使用 == 和 ===
if (obj.a == null) {
    /*
        这里相当于 obj.a === null || obj.a === undefined, 简写形式
        这是jQuery源码的推荐写法
        除此之外都是用 ===
    */
}

function (a, b) {
    if (a == null) {
        // 这里也可以使用 == ,但是 == 之前的变量必须要有定义
    }
}

‘’(空字符串), 0, null, undefined都可以转换为 false

  1. JS中的内置函数–数据封装对象
    Object、Number、String、Boolean、Function、Array、Date、RegExp、Error
  2. JS变量按存储方式区分为那些类型,并描述其特点

值类型

var a = 100;
var b = a;
a = 200;
console.log(b) // 100

引用类型:对象、数组、函数(节省内存空间,以指针方式存储)

var obj1 = {x: 20};
var obj2 = obj1;
obj1.x = 30;
console.log(obj2.x) // 30
  1. 如何理解JSON
    JSON只是JS的一个内置对象,Math也是.JSON 常用的两个 API 如下
// 把对象转换成字符串
JSON.stringify({a:10, b:20}) 
// 把字符串转换成对象
JSON.parse('{"a":10, "b":20}') 

原型和原型链

知识点

  • 构造函数
  • 构造函数 - 扩展
  • 原型规则和示例
  • 原型链
  • instanceof

构造函数

function Foo(name, age) {
    this.name = name;
    this.age = age;
    this.class = 'class one';
    //return this  //默认有这一行
}
// 创建多个对象
var f1 = new Foo('zhansan', 12);
var f2 = new Foo('lise', 13);

构造函数的扩展

  • var a = {} 其实是 var a = new Object() 的语法糖
  • var a = [] 其实是 var a = new Array() 的语法糖
  • function Foo() {...} 其实是 var Foo = new Funcion() {...} 的语法糖
  • 使用 instanceof 判断一个函数是否是一个变量的构造函数

原型规则和实例

  • 所有的引用类型(对象、数组、函数),都具有对象特性,即可自由扩展属性(除了”null”以外
  • 所有的引用类型(对象、数组、函数),都有一个proto(隐式原型)属性,属性值是一个普通对象
  • 所有的函数,都有一个prototype(显示原型)属性,属性值是一个普通对象
  • 所有的引用类型(对象、数组、函数),proto属性值指向它的构造函数的 prototype 属性值
  • 当试图寻找一个对象(引用类型)的某个属性时,如果这个对象本身没有这个睡醒,那么会去它的proto(即它的构造函数的prototype)中去寻找
// 所有的引用类型都有可自由扩展属性
var obj = {};
obj.a = 100;
var arr =[];
arr.a = 200;
function fn() {};
fn.a = 100;

// 所有的引用类型都有一个默认的隐式原型属性
console.log(obj._proto_);
console.log(arr._proto_);
console.log(fn._proto_);

// 所有的函数都有一个显示原型的属性
console.log(fn.prototype);


// 所有引用类型的_proto_属性值指向它的构造函数的prototype属性值
console.log(obj._proto_ === Object.prototype);

// 构造函数
function Foo(name, age) {
    this.name = name;
}
Foo.prototype.alertName = function () {
    alert(this.name);
}

// 创建实例
var f = new Foo('zhangsan');
f.printName = function () {
    console.log(this.name);
}

// 测试
f.alertName();
f.printName();

// 循环对象自身的属性
var item;
for (item in f) {
    /*
        高级浏览器已经在 for in 中屏蔽了来自原型的属性
        但还是建议加上下面这个判断,保证程序的健壮性
    */
    if (f.hasOwnProperty(item)) {
        console.log(item);
    }
}

// 原型链
f.toString() // 要去 f._proto_._proto_ 中查找

instanceof

用于判断引用类型属于哪个构造函数的方法
intanceof Foo 的判断逻辑:

  1. f.proto 一层一层往上,能否对应到 Foo.prototype

  2. 再试着判断 f instanceof Object

  3. 同样在 f.proto 一层一层往上找,直到 Object.prototype

  4. 如何准确判断一个变量是数组类型

var arr = [];
arr instanceof Array; // true
typeof arr; // Object, typeof 是无法判断是否为数组的
  1. 写一个原型链继承的例子
// 动物
function Animal() {
    this.eat = function () {
        console.log('Animal eat');
    }
}
// 狗
function Dog() {
    this.bark = function () {
        console.log('dog bark');
    }
}
Dog.prototype = new Animal();
// 哈士奇
var hashiqi = new Dog();
hashiqi.eat();
hashiqi.bark()

面试中千万不要上面的例子,应该写更加贴近实战的例子,上面这个例子只是用来理解。

  1. 利用原型链继承实现一个封装DOM查询的例子
function Elem(id) {
    this.Elem = document.getElementById(id);
}
Elem.prototype.html = function (val) {
    var elem = this. Elem;
    if (val) {
        elem.innerHTML = val;
        return this;//为了后边的链式操作
    } else {
        return elem.innerHTML
    }
}
Elem.prototype.on = function (type, fn) {
    var elem = this.Elem;
    elem.addEventListener(type, fn);
    return this;////如果添加return this,后边还可以接链式操作
}

4.javascript封装document.getElementById()方法

//封装一个获取元素的fun  
function byId(id){  
    return typeof(id) === "string"?document.getElementById(id):id;    
} 

解析:

  • 因为Html中元素的id名称一般为字符串类型,所以用typeof判断其类型是否为string;
  • "==="叫做严格运算符,先判断数据的类型,相同的前提下在判断数据的值;
  • 通过三元运算进行判断,如果为true则获取该id的元素,如果为false则返回id的值;

切记id的值为字符串,所有要在id的值上加上引号,eg:"div1"

  1. 描述 new 一个对象的过程
  • 创建一个新对象
  • this 指向这个新对象
  • 执行代码,即对 this 进行赋值
  • 返回 this
  1. zepto(或其他框架)源码中如何使用原型链(不知道就先这样回答)
    1.阅读源码是高效提升技能的方式
    2.但不能“埋头苦研”有技巧在其中,阅读之前在网上先搜索一下资料

javascript的四种继承方式

定义一个父类

// 父类:动物类
function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};
  1. 原型链继承
function Cat(){}
Cat.prototype = new Animal();//继承父类的原型
Cat.prototype.name = 'cat'; //添加子类原型属性
var cat = new Cat();

console.log(cat.name);//cat
cat.eat('fish');//cat正在吃fish
cat.sleep();//cat正在睡觉

//cat即是Animal的实例也是Cat的实例
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true

原型链概念:每个对象都会在其内部初始化一个属性,就是prototype(原型),
当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,
这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
特点:

  • 实例是子类Cat的实例,也是父类Animal的实例
  • 父类新增原型方法/原型属性,子类都能访问到

缺点:

  • 要想为子类新增属性和方法,必须要在继承(new Animal()这样的语句)之后执行,不能放到构造器中
  • 无法实现多继承
  1. 构造继承
function Cat(name){
  //call的用法就是执行Animal构造函数,对象指向this,也就是Cat的this,也可以理解为Cat继承了Animal
  Animal.call(this);
  this.name = name || 'Tom';
}

var cat = new Cat();
console.log(cat.name);//Tom
cat.sleep();//Tom正在睡觉
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特点:

  • 子类实例不再是父类的实例 不再共享引用属性
  • 创建子类实例,可以向父类传递参数
  • 可以实现多继承(call多个父类对象)

缺点:

  • 实例不是父类的实例,这有时也是一个缺点;
  • 只能继承父类的实例属性和方法,不能继承原型属性/方法(构造继承与原型无关);
  1. 实例继承
function Cat(name){
  var instance = new Animal();//定义父类的实例
  instance.name = name || 'Tom';//定义实例的属性为子类的属性
  return instance;//返回实例
}

var cat = new Cat();
console.log(cat.name);//Tom
cat.sleep();//Tom正在睡觉
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false

特点:

  • 容易理解,实例是父类的,换上子类的属性,返回出来

缺点:

  • 实例是父类的实例,不是子类的实例
  • 不支持多继
  1. 拷贝继承
function Cat(name){
  var animal = new Animal();
  for(var p in animal){
    Cat.prototype[p] = animal[p];
  }
  Cat.prototype.name = name || 'Tom';
}

var cat = new Cat();
console.log(cat.name);
cat.sleep();
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特点:

  • 支持多继承

缺点:

  • 效率较低,内存占用高(因为要拷贝父类的属性)

git 常见的错误

常见错误解决

  1. 设置远程地址:
输入:$ git remote add origin [email protected]:github帐号名/项目名.git 
提示出错信息:fatal: remote origin already exists.
解决方法:输入$ git remote rm origin
再输入:$ git remote add origin [email protected]:github帐号名/项目名.git
  1. 提交到远程仓库
如果输入$ git push origin master
提示出错信息:error:failed to push som refs to .......
先输入$ git pull origin master //先把远程服务器github上面的文件拉下来
再输入$ git push origin master

小程序总结一

什么是小程序

小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者
搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心是否安装太多应用的问题。应用
将无处不在,随时可用,但又无需安装卸载。
 ——张小龙

特点:随时可用,触手可及 适用于业务逻辑简单、使用频率低、性能要求不高的应用,比如购票应用,叫外卖应用,天气预报类应用等等


构建小程序基本结构


根目录下有 3 个文件:app.js、app.json、app.wxss

pages 文件夹下的页面都是由 4 个文件构成的,分别是:.wxml、.wxss、.js 和 .json 文件,这四个文件也是类似于前端 Web 页面中的 HTML (骨架),
CSS (样式),JS (逻辑),JSON (配置)

wxss 样式跟 json 配置有一个就近原则,如果 wxss,json 的配置冲突,那么就会以页面最近的配置为准

app.js /app.json /welcome.json/welcome.wxml默认必填,不然会报错

// app.js

{
  "pages":[
    "pages/welcome/welcome"
  ]
}

每新建一个页面,都需要在 app.json 中注册,app.json 当中的代码是一个 json 对象,该对象的第一个属性 pages 接受一个数组,数组的每一项都是一个字符串,
用来指定我们的小程序将由哪些页面组成,每一项由对应页面的【路径 + 文件名】组成

小程序不可以使用现在已存在的 JavaScript 组件库,例如 JQuery,因为小程序不支持 DOM 操作,在小程序中没有 windows 对象,以 DOM 为操作对象的组件库都无法使用
所以 js 文件我们需要使用原生 JavaScript 进行编写,微信开发者工具也提供了 ES6 转 ES5 功能,不过该功能只会帮助开发者处理语法上的问题,新的 ES6 的 API,例如 Promise
等需要开发者自行引入 Polyfill 或者别的类库。同时,为了提高代码质量,在开启 ES6 转换功能的情况下,默认启用 JavaScript 严格模式。

// app.json
Page({
  
})
// welcome.json
{
}

json 文件中无法添加注释


必备的知识

  • 小程序对flex布局很好的支持,不需要写浏览器兼容样式
  • 一般的视觉稿都是参照 iPhone 6 的 750 × 1334 的分辨率进行设计的,这里的分辨率指的是物理分辨率 px,而我们在模拟器当中,iPhone 6 的分辨率为 375 × 667,
    模拟器当中的分辨率指的是逻辑分辨率 pt,可以看到物理分辨率跟逻辑分辨率是2:1的关系,所以我们一般会把在视觉稿量出的尺寸减半,写到样式中
  • rpx 可以使组件自适应屏幕的高度和宽度,能够使页面适用不同机型、不同分辨率的手机上,但 px 不会,只是让元素始终保持不变
  • 通过设置导航栏和页面的颜色一致可以让小程序顶部 的导航栏已经被“隐藏”

window 配置项

  1. navigationBarTextStyle 配置导航栏文字颜色,只支持 black/white
  2. navigationBarTitleText 配置导航栏文字内容
  3. backgroundColor 配置窗口颜色
  4. backgroundTextStyle 下拉背景字体,仅支持 dark/light
  5. enablePullDownRefresh 是否开启下拉刷新

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.