目录
首先
在echarts中,修改地图的边界的颜色
geo: {
map: 'china',
label: {
emphasis: {
show: false
}
},
roam: true,
itemStyle: {
normal: {
areaColor: '#323c48', //这里是这是地图边界颜色的
borderColor: 'red'
},
emphasis: {
areaColor: '#2a333d'
}
}
}
然后,开始一段新的征程
一些有趣的获取每个月多少天的代码
我常用的写法(非常普通的)
function getMonthDays(time) {
var year = parseInt(time);
var month = Number(time.substr(-2));
return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month-1] || (isLeapYear(year) ? 29 : 28);
}
高级那么一丁点的写法(这个和我用的差不多)
const EVERY_MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
function getDays(year, month) {
if (month === 1 && isLeap(year)) return 29;
return EVERY_MONTH_DAYS[month];
}
function isLeap(year){
return ((year%4==0&&year%100!=0)||(year%400==0))
}
炫酷一点点的写法(第三个参数可以是可以大于我们所知道的每个月的最后一天的)
function getDays(year, month) {
if (month === 1) return new Date(year, month, 29).getMonth() === 1 ? 29 : 28;
return new Date(year, month, 31).getMonth() === month ? 31 : 30;
}
屌炸天的写法(跟上面一样,不过第三个参数传0,他就会显示上个月的最后一天是几号)
function getDays(year, month) {
return new Date(year, month + 1, 0).getDate();
}
接着,我们来看一下把时间转换为标准格式的方法
同样,白痴的方法(实际上并不白痴,很使用的一种方法)PS:注意最後的正则使用的很好
let date = new Date();
let result = [
[
date.getFullYear(),
date.getMonth() + 1,
date.getDate()
].join('-'),
[
date.getHours(),
date.getMinutes(),
date.getSeconds()
].join(':')
].join(' ').replace(/\b\d\b/g, '0$&');//匹配边界然后加上0,正则匹配只有一位数字的加上0
精妙的方法
var date = new Date();
var result = date.toLocaleString('zh-CN', { hour12: false })
.replace(/\//g, '-').replace(/\b\d\b/g, '0$&');
下面我们来看看一些比较杂乱的东西
都是我一点点总结出来的,有的没写答案
变量提升的问题
// 调用被提升的函数
addition(4, 7); // => 11// 变量被提升了,但值是undefined
substraction(10, 7); // TypeError: substraction is not a function
// 函数声明
function addition(num1, num2) {
return num1 + num2;}// 函数表达式var substraction = function (num1, num2) {
return num1 - num2;};
addition被彻底的提升并且可以在声明之前被调用。然而substraction是使用变量声明语句声明的,虽然也被提升了,但被调用时值是undefined。因此会抛出异常TypeError: substraction is not a function。
再来看这个变量提升的问题,关于ES6的
function isTruthy(value) {
var myVariable = 'Value 1';
if (value) {
/**
* myVariable的临时死亡区间
*/
console.log(myVariable);// Throws ReferenceError: myVariable is not defined
let myVariable = 'Value 2';
// myVariable的临时死亡区间至此结束
console.log(myVariable); // => 'Value 2'
return true;
}
return false;}
isTruthy(1); // => true
从let myVariable一行一直到代码块开始的if (valaue) {...}都是myVariable变量的临时死亡区间。如果在此区间内访问该变量,JavaScript会抛出ReferenceError异常。
一个有趣的问题出现了:myVariable真的被提升到代码块顶部了吗?还是在临时死亡区间内未定义呢?当一个变量未被定义时,JavaScript也会抛出ReferenceError。
如果你观察一下该函数的开始部分就会发现,var myVariable = 'Value 1'在整个函数作用域内定义了一个名为myVariable的变量。在if (value) {...}块内,如果let定义的变量没有被提升,那么在临时死亡区间内myVariable的值就会是'Value1'了。由此我们可以确认块级变量确实被提升了。
let在块级作用域内的提升保护了变量不受外层作用域影响。在临时死亡区间内访问let定义的变量时抛出异常会促使开发者遵循更好的编码实践:先声明,后使用。
这两个限制是促使在封装性和代码流程方面编写更好的JavaScript的有效途径。这是基于var用法教训的结果 —— 允许在声明之前访问变量很容易造成误解。
来模拟一个map的方法
Array.prototype.map = function(fn){
var a = [];
for(var i = 0; i < this.length; i++){
var value = fn(this[i], i);
if(value == null){
continue; //如果函数fn返回null,则从数组中删除该项
}
a.push(value);
}
return a;
};
array.map(callback[, thisArg]);
map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。callback 函数会被自动传入三个参数:数组元素,元素索引,原数组本身。如果 thisArg 参数有值,则每次 callback 函数被调用的时候,this 都会指向 thisArg 参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 null 或 undefined,则 this 指向全局对象 。
map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。当一个数组运行 map 方法时,数组的长度在调用第一次callback 方法之前就已经确定。在 map 方法整个运行过程中,不管 callback 函数中的操作给原数组是添加还是删除了元素。
map 方法都不会知道,如果数组元素增加,则新增加的元素不会被 map 遍历到,如果数组元素减少,则 map 方法还会认为原数组的长度没变,从而导致数组访问越界。如果数组中的元素被改变或删除,则他们被传入 callback 的值是 map 方法遍历到他们那一刻时的值。
另一种方法
if (!Array.prototype.map)
{
Array.prototype.map = function(fun /*, thisp*/)
{
var len = this.length;
if (typeof fun != "function")
throw new TypeError();
var res = new Array(len);
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in this)
res[i] = fun.call(thisp, this[i], i, this);
}
return res;
};
}
Object.create
Object.create(proto [, propertiesObject ]) 是E5中提出的一种新的对象创建方式,第一个参数是要继承的原型,如果不是一个子函数,可以传一个null,第二个参数是对象的属性描述符,这个参数是可选的。创建原型继承
propertiesObject 参数的详细解释:(默认都为false)
数据属性:
writable:是否可任意写
configurable:是否能够删除,是否能够被修改
enumerable:是否能用 for in 枚举
value:值
访问属性:
get(): 访问
set(): 设置
两种不常见的css隐藏
.hide{position: absolute;top: -9999px;left: -9999px; }
.hide{ clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px); }
css模拟拿起放下的效果
<div class = "floating"></div>
.floating {
position: relative;
width:100px;
height:100px;
bbackground:red;
transform: translateY(0);
transition: transform 1s;}
.floating:after {
content: "";
display: block;
position: absolute;
bottom: -30px;
left: 50%;
height: 8px;
width: 100%;
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.4);
border-radius: 50%;
background-color: rgba(0, 0, 0, 0.2);
transform: translate(-50%, 0);
transition: transform 1s;}
/* Hover States */.floating:hover {
transform: translateY(-40px);
transition: transform 1s;}.floating:hover:after {
transform: translate(-50%, 40px) scale(0.75);
transition: transform 1s;}
下面进入正题this的一些问题
题1.
// 写出以下代码的运行结果
var a = 1;
function fn() {
if (!a) {
var a = 2; //这里的var会提升到fn下面
}
alert(a); // ? 2
}
fn();
题2
// 写出以下代码的运行结果
var a = 1;
function fn() {
a = 2;
return;
function a() {} //首先会提升到fn下面,然后a是局部变量
//注意变量与函数同名之后,变量相当于局部变量了,函数提升为a = function(){}
}
fn();
alert(a); // ? 1
题3
a= 10;
(function a(){
a = 1;
console.log(a);// ? functiona(){ a是function,匿名函数的函数名可以在函数内部访问
// a = 1;
// console.log(a);
// }
})();
题4
function a(){
console.log(aa); //这里aa是undefined,在不同的浏览器下不一样,最新版chrome是undefined,其他的都是function
if(1){
function aa(){
console.log(11);
}
}
}
题5
var a = 1,
b = function a (x) { //b是局部变量
x && a (--x);
};
alert (a);
alert(b(a));//undifined,最后函数返回0
我们可以用多个逗号将变量分开定义,而是用一个var。函数表达式类似于局部变量,不会被全局作用域中访问到。
执行顺序:
声明两个变量var a,b;
并给他们赋值a=1,b=function a(){...};
这里的function a是局部变量,外部无法访问到。
因此全局a还是1.
题6
var test = 111;
function _add()
{
// this.test = 444; //注释①
alert(this.test);
}
function _sub()
{
this.test = 222;
alert(this.test);
}
_add();
_sub();
_add.call(_sub); //有注释①:undefined 去掉:444,this指向sub,这是sub执行add里面的方法,然后调用的add的方法this.test = 444;
var d = new _add();//结果等同于_add.call(_sub);
a.call(b)里面的是作用域相当于在b里面执行a的方法,a.call(this)这个this是window,在window里面执行a的方法
题7
var name = 1;
function show(){
console.log(name);//1,因为show没有参数,所以name传不进来!!!WTF
}
function main(){
var name =2;
show();
}
main()
题8
function a(xx){
this.x=xx;
return this
};
var x=a(5);
var y=a(6); //注意是两句运行完之后再打印的
console.log(x.x); //undefined
console.log(y.x); //6
function Foo() {
getName = function () { alert (1); };
return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}
//请写出以下输出结果:
Foo.getName(); //2
getName(); //4
Foo().getName();//5 1 //重新定义window.getName
getName();//4 1
new Foo.getName();//2 只有函数才能new,单对象new {} 是错误的
new Foo().getName();//1 3
new new Foo().getName(); //3 执行顺序new((new Foo)().getName)()
这是对 this 的描述
https://segmentfault.com/q/1010000003019911
JavaScript 中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。
----(JavaScript 高级程序设计)
我知道 this 的指向一般分 4 种情况:
(1)作为构造函数调用,指向构造函数生成的对象;
(2)作为函数调用,指向去全局变量
(3)作为对象的方法调用,指向到该对象
(4)使用 call 或者 apply 方法,this 指定 call 或者 apply 方法指定的执行环境。。
继续做题
题10
ar length = 10;
function fn(){
alert(this.length);
}
var obj = {
length: 5,
method: function(fn) {
fn() // 10 这里得fn跟不是传进来的参数,只是调用外部的函数所以this是全局
arguments[0]() // 1 这里是传参进来的fn,但是他的作用域是arguments,所以是1
}
}
obj.method(fn)
题11
~function() { //~表示匿名函数
alert(typeof next) // undefined
~function next() {
alert(typeof next) // function
}()
}()
题12
var a=function b(){};
alert(typeof b);
根据 ECMA 规范中的规定,以上函数表达式中的标识符 b 将仅在该函数的内部可以被访问,即 b 仅在该函数的作用域内有效,外部无法访问。
题13
function a(b){ function a(b){ //b传值进来就被覆盖了 //http://blog.csdn.net/zxc123e/article/details/37052155
alert(b); var b = function(){
function b(){ alert(b);
alert(b); }
} alert(b);
b(); b();
} }
a(1); a(1);
题14
(function(){
var a = b = 3; //b是全局啊!!!!
})();
console.log(a); //undefined
console.log(b); //3
题15
function foo1() //http://www.2cto.com/kf/201512/454888.html
{
return {
bar: "hello"
};
}
function foo2()
{
return
{
bar: "hello"
};
};
foo1();
foo2();
题16
function add(num1, num2){ //js精度问题处理加法
let r1, r2, m;
r1 = (''+num1).split('.')[1].length;
r2 = (''+num2).split('.')[1].length;
m = Math.pow(10,Math.max(r1,r2));
return (num1 * m + num2 * m) / m;
}
console.log(add(0.1,0.2)); //0.3
console.log(add(0.15,0.2256));
题17
//写一个少于 80 字符的函数,判断一个字符串是不是回文字符串
function isPalindrome(str) {
str = str.replace(/\W/g, '').toLowerCase();
return (str == str.split('').reverse().join(''));
}
题18
CSS计数器只能跟content属性在一起的时候才有作用,counter 只能在content 里面使用,而content属性貌似专门用在before/after伪元素上的。于是,就有了,“计数器↔伪元素↔content属性”的铁三角关系。
.xxx { counter-reset: wangxiaoer 2 wangxiaosan 3; } //对counter进行初始化,中间只能用空格分隔
counter-reset还可以设置为none和inherit. 干掉重置以及继承重置。
counter-increment使用一次,counter-reset值增加,默认递增1
题19
//数组去重
if(!Array.prototype.unqine){
Array.prototype.unqine = function(){
var a =[];//定义一个临时数组用于装数据
for(var i = 0; i < this.length; i++){
if(a.indexOf(this[i]) === -1) a.push(this[i]);
}
return a;
}
}
var arr = [8,8,8,8,8,8,9,0,1,5,6,7,8,1,4,3,2,4];
console.log(arr.unqine());//[8, 9, 0, 1, 5, 6, 7, 4, 3, 2]
//兼容IE
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(val) {
for (var i = 0; i < this.length; i++) {
if (this[i] === val)return i;
}
return -1;
}
}
完 2016/8/3