Javascript toString() toLocaleString()

一、JS Array

toString():把数组转换为字符串,并返回结果,每一项以逗号分割。

toLocalString():把数组转换为本地数组,并返回结果。

二、JS Date

var date = new Date();
console.log(date.valueOf());
console.log(date.toString());
console.log(date.toLocaleString());

877488-20160723162010044-2046268350.png

valueOf:返回 Date 对象的原始值,以毫秒表示。

toString():把 Date 对象转换为字符串,并返回结果。使用本地时间表示。

toLocalString():可根据本地时间把 Date 对象转换为字符串,并返回结果,返回的字符串根据本地规则格式化

三、JS Number

var num = new Number(1337);
console.log(num.valueOf());
console.log(num.toString());
console.log(num.toLocaleString());

877488-20160723163156076-119578640.png

valueOf:返回一个 Number 对象的基本数字值。

toString():把数字转换为字符串,使用指定的基数。

toLocalString():把数字转换为字符串,使用本地数字格式顺序。

四、toString()方法与toLocalString()方法区别:

  • toLocalString()是调用每个数组元素的 toLocaleString()
    方法,然后使用地区特定的分隔符把生成的字符串连接起来,形成一个字符串。

    toString()方法获取的是String(传统字符串),而toLocaleString()方法获取的是LocaleString(本地环境字符串)。
    如果你开发的脚本在世界范围都有人使用,那么将对象转换成字符串时请使用toString()方法来完成。

    LocaleString()会根据你机器的本地环境来返回字符串,它和toString()返回的值在不同的本地环境下使用的符号会有微妙的变化。

    所以使用toString()是保险的,返回唯一值的方法,它不会因为本地环境的改变而发生变化。如果是为了返回时间类型的数据,推荐使用LocaleString()。若是在后台处理字符串,请务必使用toString()。

4793560936

首先可以吐槽一下在安装的时候就一直报错报错,然后花了很长时间

ant design 在安装的时候会依赖很多库最重要的三个需要安装期中在安装react,react-dom各种版本依赖而且还不支持最新版本的react-native 所以需要安装旧版本的react-native

指定react-native版本创建项目 :

  1. 查看react-native 版本信息

    npm info react-native

  2. 安装rninit
    rninit.png

  1. Ant design 安装步骤

    制定旧版本react-native创建项目

 rninit init Ant(项目名称) --source react-native@0.41.2
    npm i
    npm start
    全局安装
    sudo npm i react-native-cli -g /注意全局安装的时候制定权限否则安装报错
    antdesign在安装的时候依赖各种库所以在安装之前先要安装react 及react-dom
    npm install react@15.4.2 /这个应该是自动安装的可以省略直接安装 react-dom@15.4.2
    npm install react-dom@15.4.2 


.babelrc添加配置,参考官方git代码
{
  "presets": ["react-native"],
  "plugins": [["import", { "libraryName": "antd-mobile" }]]
}
index.ios.js实例:



 import React, { Component } from 'react';
    import { DatePicker, List } from 'antd-mobile';
    import { AppRegistry, View } from 'react-native';
    
    export default class AntdMobieDemo extends Component {
      render() {
        return (<View style={{ marginTop: 30 }}>
          <List>
            <DatePicker mode="datetime">
              <List.Item arrow="horizontal">
                选择时间
              </List.Item>
            </DatePicker>
          </List>
        </View>);
      }
    }
    
    / change xxxxx to your project name
    AppRegistry.registerComponent('xxxxx', () => AntdMobieDemo);

(509) 230-9784

在函数内部,有两个特殊的对象:arguments 和 this。其中, arguments 的主要用途是保存函数参数, 但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。 请看下面这个非常经典的阶乘函数

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

定义阶乘函数一般都要用到递归算法;如上面的代码所示,在函数有名字,而且名字以后也不会变 的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为 了消除这种紧密耦合的现象,可以像下面这样使用 arguments.callee

function factorial(num){    
   if (num <=1) {         
      return 1;     
   } else {         
   return num * arguments.callee(num-1);
   } 
}  

在这个重写后的 factorial()函数的函数体内,没有再引用函数名 factorial。这样,无论引用 函数时使用的是什么名字,都可以保证正常完成递归调用。例如

function factorial(num){
        if(num <= 1){
            return 1;
        }else{
            return num * arguments.callee(num-1);
        }
    }
    var trueFactorial = factorial;
    alert(trueFactorial(5));    /120    


    factorial = function() {
        return 0;
    }                
    alert(trueFactorial(5));/ 120 如果没有使用arguments.callee,将返回0

在此,变量 trueFactorial 获得了 factorial 的值,实际上是在另一个位置上保存了一个函数 的指针。然后,我们又将一个简单地返回 0的函数赋值给 factorial 变量。如果像原来的 factorial() 那样不使用 arguments.callee,调用 trueFactorial()就会返回 0。可是,在解除了函数体内的代 码与函数名的耦合状态之后,trueFactorial()仍然能够正常地计算阶乘;至于 factorial(),它现 在只是一个返回 0的函数。

现在已经不推荐使用arguments.callee();

原因:访问 arguments 是个很昂贵的操作,因为它是个很大的对象,每次递归调用时都需要重新创建。影响现代浏览器的性能,还会影响闭包。

不能用怎么办?

像第三段中的例子,重写 factorial()方法导致trueFactorial()结果不在预期。是为了演示而做的。平时写代码应该避免。

递归时用到arguments.callee()是常见的事情,比如

一道面试题。接受参数n=5,不用for循环输出数组【1,2,3,4,5】

这用递归的思路,配合arguments.callee,代码如下

function show(n) {
    var arr = [];
    return (function () {
        arr.unshift(n);
        n--;
        if (n != 0) {
            arguments.callee();
        }
        return arr;
    })()
}
show(5)/[1,2,3,4,5]

现在arguments.callee 被弃用了。怎么办,其实很简单,给内部函数一个名字即可

function show(n) {
    var arr = [];
    return (function fn() {
        arr.unshift(n);
        n--;
        if (n != 0) {
            fn();
        }
        return arr;

    })()
}
show(5)/[1,2,3,4,5]

移动端事件摇一摇/手势操作

摇一摇

<script>
var lastx = 0;
var lastY = 0;
var lastZ = 0;
var box = document.querySelector("#box");
/ 设置一个值,大于max时,用户就在摇一摇
var max = 15;
var maxRange = 20;
var minRange = 10;
var isShake = false;
/摇一摇记录上次加速度与当前加速度相减,差值大于一定幅度时,用户就可以进行摇一摇
window.addEventListener('devicemotion',function(ev){
    var motion = ev.accelerationIncludingGravity;
    var x = Math.round(motion.x);
    var y = Math.round(motion.y);
    var z = Math.round(motion.z);
    var body = document.querySelector('body');
    / body.innerHTML = x;
    / console.log(x);
    / 摇一摇,监控摇晃幅度,上一次与现在相比较
    if (typeof lastX == 'undefined') {
        lastX = x;
        lastY = y;
        lastZ = z;
        return;
    };
    var dis = Math.abs(x - lastX) + Math.abs(y - lastY) + Math.abs(z - lastZ);
    / max = Math.max(max,dis);
    / if (dis>max) {
    /  alert("摇一摇");
    / };
    if(dis > maxRange){
        isShake = true;
    }
    if(dis < minRange && isShake){
        isShake = false;
        /执行摇一摇之后的操作
        alert("晃动手机之后的操作");
    }
    console.log(dis);
    lastX = x;
    lastY = y;
    lastZ = z;
    box.innerHTML = dis;
})
</script>

移动端手势操作:

<script>
document.addEventListener('touchstart',function(ev){
    ev.preventDefault();
})
var box = document.querySelector("#box");
/**
 * geture 相关事件只有ios下有android暂不支持
 * gesturestart
 *当手指触摸元素,当前屏幕上有两根或者两根以上的手指
 * gestureend
 * 当我们触发了 gesturestart时,然后抬起手指,这时屏幕上的手指个数少于两个或者当前元素上没有手指就会触发gestureend  
 * gesturechange
 * 当我们触发了gesturestart时,手指位置发生变化时
 * 
 */
box.addEventListener('gesturestart',function(e){
    this.style.background = "#00f"; 
})
box.addEventListener('gestureend',function(e){
    this.style.background = "#0f0"; 
})
/ 图片缩放
box.addEventListener('gesturechange',function(e){
    /e.scale 缩放比,change时两根手指的距离和start时两根手指之间的距离比值
    this.innerHTML = e.scale;
    console.log(e.scale);
    / 角度差/旋转差
    / start时两根手指的直线,与change时两根手指的直线形成的夹角
    this.innerHTML = e.rotation;
})
var image = document.querySelector("#image");
var startScale = 0;
image.addEventListener('gestureStart',function(e){
    / js获取scale,会转为matrix所以要获取scale需要封装css方法
    startScale = css(image,'scale');
})
image.addEventListener('gesturechange',function(e){
    / 直接设置scale存在bug
    / this.style.WebitTransform = this.style.transform = 'scale('+e.scale+')';
    css(image,'scale',e.scale*startScale);
})
/ 双指旋转
image.addEventListener('gestureStart',function(){
    startRotate = css(image,'rotate');
}
image.addEventListener('gesturechange',function(e){ 
    css(image,'rotate',e.rotation+startRotate);
})
</script>

移动端rem布局及基础事件

rem布局非常简单,首页你只需在页面引入这段原生js代码就可以了

(function (doc, win) {
    var docEl = doc.documentElement,
        resizeEvt = 'onorientationchange' in window ? 'onorientationchange' : 'resize',
        recalc = function () {
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            if(clientWidth>=750){
                docEl.style.fontSize = '100px';
            }else{
                docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
            }
        };

    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

如何使用?

这是rem布局的核心代码,这段代码的大意是:
如果页面的宽度超过了750px,那么页面中html的font-size恒为100px,否则,页面中html的font-size的大小为: 100 * (当前页面宽度 / 750)

于是,问题来了,为什么要这样?别急,我先来一一回答

为什么是750px?

对于手机屏幕来说,750px的页面宽度是一个安全的最大宽度,保证了移动端页面两边不会留白。注意这里的px是css逻辑像素,与设备的物理像素是有区别的。如iPhone 5使用的是Retina视网膜屏幕,使用2px x 2px的 device pixel 代表 1px x 1px 的 css pixel,所以设备像素数为750 x 1136px,而它的CSS逻辑像素数为375 x 568px。如果要切移动端页面,你可以先把效果图宽度等比例缩放到750px,很好用。

为什么要设置html的font-size?

rem就是根元素(即:html)的字体大小。html中的所有标签样式凡是涉及到尺寸的(如: height,width,padding,margin,font-size。甚至,left,top等)你都可以放心大胆的用rem作单位。
如果你把html的font-size设为20px,前面说过,rem就是html的字体大小,那么1rem = 20px。此时,此时宽60px,高40px的元素样式就这样设置如下 ↓

width: 3rem;
height: 2rem;

那要是宽55px,高37px呢?然后经过换算,,设置如下 ↓

width: 2.75rem;
height: 1.85rem;

是不是发现这换算起来有点麻烦啊,,,(当然,你要是心算帝请无视)如果我们一开始把html的font-size设为100px呢?此时1rem = 100px,那么上面的宽,高就可以这么设置 ↓

width: 0.55rem;
height: 0.37rem;

是不是换算起来简单多了?!

(当然可能有同学问,为什么不一开始把html的font-size设为1px呢,这样换算起来也简单,答:浏览器一般都有最小字体限制,比如谷歌浏览器,最小中文字体就是12px,所以实际上没有办法让1rem=1px。)
根据上面的js代码,如果页面宽度低于750px,那么页面中html的font-size也会按照(当前页面宽度/750)的比例变化。这样,页面中凡是应用了rem的作尺寸单位的元素都会随着页面变化而等比例缩放了!

都哪些情况可以用rem布局?

大部分情况下都可以用rem布局这个方法,当然具体还要看情况而定。拿我们公司项目举例,只有底部的导航不用rem,而是用的flex布局。因为导航点击最多,所以给它一个固定的大小(其实就是高度固定,宽度自适应的方案)。大家可以看看淘宝的这个手机页面 淘宝手机站,基本就是这种感觉,底部导航和顶部搜索框用的高固定,宽自适应的方案,其余的部分基本都是随着浏览器宽度变化在等比例缩放。

个人心得

在rem布局中,有一些自己积累的小技巧给大家分享下。

页面中模块间距离一般为0.2rem。字体的大小一般分为四个档次 0.2rem 0.24rem 0.28rem 0.32rem。
拿我们项目举例,我们移动端页面效果图的宽度都定在了750px。于是我在项目中,最外层的div样式就设置成了

position: relative;
 width: 100%;
 max-width: 750px;
 min-width: 320px;
 margin: 0 auto;

所有的元素都可以写在这个div中了,于是就可以开始写样式了

rem布局中,如果有个元素需要水平居中固定到页面底部,你会怎么设置它的样式呢。我是这样做的,前提是这个元素还是在前面说的最外层水平居中的大div中,样式如下

 position: fixed;
 bottom: 0;
 z-index: 100;
 width: 100%;
 max-width: 750px;
 min-width: 320px;

基础事件touchstart,touchmove,touchend:

<script>
/**
 *
 * ontouchstart,ontouchmove,ontouchend
    pc上的事件,用在移动端会造成延时大概300毫秒
    拓展:为什么时300毫秒,苹果毫秒300内双击缩放
    移动端点透:
        当上层元素发生点击的时候,下层元素也有点击事件,在300毫秒之后,如果上层消失或隐藏,目标就会漂移到下层元素身上,就会发生点击事件
    解决方法:
        1:下层不使用有点击(焦点)事件的元素
        2:阻止pc事件
            1-ios10 禁止用户缩放
            2-解决iOS10 溢出隐藏的问题
            3-禁止系统默认的滚动条,阻止橡皮筋效果
            4-禁止长按选中文字,选中菜单,系统默认菜单
            5-解决点透效果
            6-阻止元素默认事件 input
 */
/ 在移动端开发的时候,浏览器的模拟器时好时坏,一般不用on的方式绑定,要用事件的方式绑定
var div = document.getElementById("div1");
/ div.ontouchstart = function(){
/  alert(1);
/ }
div.addEventListener("touchstart",function(){
    / alert(1);
    / console.log(1);
    div.style.display = "none";
})
/ div.addEventListener('touchmove',move);
/ function move(){
/  console.log(2);
/ }
/ 2:阻止pc事件

document.addEventListener('touchstart',function(ev){
    ev.preventDefault();
})
</script>

touches,targetTouhes,changedTouches

/**
 * touches 当前位于屏幕上的所有手指的一个列表
 * targetTouches 当前DOM元素上的手指的一个列表
 * changedTouches 涉及当前事件的手指的一个列表
 */

陀螺仪:

<script>
window.onload = function(){
    document.addEventListener('touchstart',function(ev){
        ev.preventDefault();
    })
    var box = document.querySelector('#box');
    / 陀螺仪事件对象为window
    / 兼容 ios andriod android 数值相反
    window.addEventListener('devicemotion',function(e){
        var motion = e.accelerationIncludingGravity;
        / 因为陀螺仪太灵敏所以只取整数部分
        var x = Math.round(motion.x);
        var y = Math.round(motion.y);
        var z = Math.round(motion.z);
        / box.innerHTML = x + "-"+ y + "-" + z;
        / 兼容处理
        if (getAdr()) {
            x = -x;
            y = -y;
            z = -z;
        };
        box.innerHTML = "x:" + x+"<br>";
        box.innerHTML += "y:" + y+"<br>";
        box.innerHTML += "z:" + z;
    })

    / 判断机型
    var u = navigator.userAgent;
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
    var isIos = !!u.match(/\(i[^;]+;(U;)? CPU.+Mac OS X/);
    / console.log(isIos);

    function getAdr(){
        var u = navigator.userAgent;
        return u.indexOf('Android') > -1 || u.indexOf('Adr') >-1;
    }
}
</script>