一些JS基础

在函数中不定义return就会调用默认的隐形return,就是return undifind!!!

字符串部分:

es6用反引号表示多行字符串,就是1左边那个案件。

用 `你好, ${name}, 你今年${age}岁了!`代替+号拼接的字符串 '你好, ' + name + ', 你今年' + age + '岁了!'


打点调用:

toUpperCase()把一个字符串全部变为大写

toLowerCase()把一个字符串全部变为小写

indexOf()会搜索指定字符串出现的位置

substring()返回指定索引区间的子串

数组部分:

slice()就是对应String的substring()版本,它截取Array的部分元素,然后返回一个新的Array

push()向Array的末尾添加若干元素,pop()则把Array的最后一个元素删除掉

如果要往Array的头部添加若干元素,使用unshift()方法,shift()方法则把Array的第一个元素删掉

sort()可以对当前Array进行排序,它会直接修改当前Array的元素位置,直接调用时,按照默认顺序排序

reverse()把整个Array的元素给掉个个,也就是反转

splice()方法是修改Array的“万能方法”,splice(a,b,c,d)从索引a开始删除b个元素然后添加c,d元素

concat()方法把当前的Array和另一个Array连接起来,并返回一个新的Array

join()方法是一个非常实用的方法,它把当前Array的每个元素都用指定的字符串连接起来,然后返回连接后的字符串

对象部分:

正则:

^    以。。。开头

$    以。。。结尾

\w    匹配字母或数字

\d    匹配数字

.    可以匹配任意字符

\s    匹配一个空格

*匹配任意个字符(包括0个)

+    表示至少一个字符

?    表示0或1个字符

{n,m}    表示n到m个字符      

[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线

^(\d{3})-(\d{3,8})$分别定义了两个组在RegExp对象上用exec()方法提取出子串

加个?就可以让\d+采用非贪婪匹配

当我们指定g标志后,每次运行exec(),正则表达式本身会更新lastIndex属性,表示上次匹配到的最后索引

指定i标志,表示忽略大小写,m标志,表示执行多行匹配。

JSON:

如果只想输出指定属性,就用数组:JSON.stringify(xiaoming, ['name', 'skills'], ' ');

解析json就JSON.parse()

面向对象:

把要给a对象的原型指向B,看上去a就像从b继承的,a就拥有自己的属性和B的方法。

关于原型:

arr ----> Array.prototype ----> Object.prototype ----> null

对于一个数组的原型链来说,数组的方法都定义在了array.prototype上,所以arr可以直接调用这些方法而不用声明

使用构造函数去新建对象:

function Student(name) {

this.name = name;

this.hello = function () {

alert('Hello, ' + this.name + '!');

}

}

然后直接var obj = new Student("..."),这样的话,每一个用此构造函数声明的对象都会具有hello这个函数。

function(){}():函数定义+()会自动执行一次;

关于遍历:

遍历中最常用的就是for循环;for(定义;判断;判断变量改变){执行条件};但是这个也是最不好用的遍历方法,应为这个方法效率较低,会占用大量运存;

一般来说对于对象,最好时用for。。。in来遍历,便利完了之后输出的是某键值对的值,格式是字符串。

for(var a in obj){alert (a)};这里的a是临时的一个变量,每次循环都会把对应的键值以string的格式保存在a中,a每次只保存一个string,循环结束后保留最后一个键值;如果只想找到对象自身的属性,而不是通过原型继承过来的就obj.hasOwnProperty(a);这个为true就是自己有的;如果用这个来遍历数组那得到的是a就是数组的每个索引值;

while和do   while就是满足条件运行,不然就结束,不过dowhile是先执行一次在判断;

关于map和set结构(类型)

map是es6里新定义的一组键值对的结构:var m=new Map()/new Map([['6666',1],['jame',2]);如此从map中取键值对就很块:m.get('jame')得到的就是2;初始化一个map需要一个空或者一个二维数组;有以下方法:

var m = new Map(); // 空Map

m.set('Adam', 67); // 添加新的key-value

m.has('Adam'); // 是否存在key 'Adam': true

m.get('Adam'); // 67

m.delete('Adam'); // 删除key 'Adam'

m.get('Adam'); // undefined

因为一个键名只能对应一个键值,所以多次存储键值会覆盖;

对于set而言其实是跟map一样的,不过map不存储value,只是一组key的集合,由于key是不可重复的,所以set中没有重复的元素,初始化一个set需要空或者一个数组,重复元素会被自动剔除; s.add(4)通过add可以添加元素

对于map和set而言都不具备下标,即索引,所以是不能用for进行循环遍历的,为此es6引入了新的iterable类型,数组,mapset都是这个类型,是可以通过for   of遍历 

而for   of的用法和for in是一样的,区别在于for in会遍历额外添加的属性,而for of只会遍历集合本身的属性

或者直接使用forEach()是es5引入的;用foreach接收一个函数,每一次遍历就会回掉该函数

例如

var a = ['A', 'B', 'C'];

var s = new Set(['A', 'B', 'C']);

var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);

a.forEach(function (element, index, array) {

// element: 指向当前元素的值

// index: 指向当前索引

// array: 指向Array对象本身

alert(element);

});

s.forEach(function (element, sameElement, set) {

alert(element);

});

m.forEach(function (value, key, map) {

alert(value);

});

对于函数:对于函数而言有一个只在函数内部有用的关键字:arguments,永远指向当前函数的传入所有参数;rest参数是只能够写在最后的形参,写作...rest,实际的传参多于形参的部分会被填充成数组存在rest下。

变量作用域:

在函数内部定义,就只作用于内部,外部无法调用,如果定义在使用之后,会自动提升变量的声明,但是不会提升变量的赋值,全局定义的变量会绑定到window上,最好是定义一个全局变量,然后把所有的变量和函数定义到这个全局变量之中,就不会出现文件的冲突了。使用let在局部作用域中声明变量;用const来声明一个常量。

方法:

方法就是绑定到对象上的函数:

var xiaoming = {

name: '小明',

birth: 1990,

age: function () {

var y = new Date().getFullYear();

return y - this.birth;

}

};

xiaoming.age; // function xiaoming.age()

xiaoming.age(); // 今年调用是25,明年调用就变成26了

this是指向调用时的对象;最好在使用的时候现在函数内部定义var that = this;先用that捕获到this指向的函数,然后用that。调用,定义其他函数;

或者是使用apply()这是函数本身的方法:age.apply(a,b)意思是this指向A,传入参数为B。

可以用作计数:

var count = 0;

var oldParseInt = parseInt; // 保存原函数

window.parseInt = function () {

count += 1;

return oldParseInt.apply(null, arguments); // 调用原函数

};

// 测试:

parseInt('10');

parseInt('20');

parseInt('30');

count; // 3

关于一些方法:

map():

遍历数组;就是把一个函数作用在每一个元素上并生成一个新的数组

function pow(x) {

return x * x;

}

var arr = [1,2,3,4,5,6,7,8,9];

arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]

reduce():

把一个函数轮流作用在每个元素上并返回一个值:

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)

filter():

和map()差不多,但是是依次作用于数组之后返回一个布尔值,根据布尔值决定是否保留该元素;true就保留,false就不保留;

var arr = [1, 2, 4, 5, 6, 9, 10, 15];

var r = arr.filter(function (x) {

return x % 2 !== 0;

});

r; // [1, 5, 9, 15]

在filter里接受的回掉函数可以有多个参数额,通常是某个元素,位置,数字本身,也就是(element,index,self)

所以去重的话;r = arr.filter(function (element, index, self) {

    return self.indexOf(element) === index;

});

就可以了

sort();

对于sort,是一种快速地数组排序方法,arr.sort()但是排序的默认依据是ASCII码,如果需要使用自定的规则:

var arr = [10, 20, 1, 2];

arr.sort(function (x, y) {

if (x < y) {

return -1;

}

if (x > y) {

return 1;

}

return 0;

}); // [1, 2, 10, 20]

而且sort方法是直接对数组的修改,他返回的结果是当前的数组。

闭包:

不立即调用该函数,在后面按需调用:

function lazy_sum(arr) {

var sum = function () {

return arr.reduce(function (x, y) {

return x + y;

});

}

return sum;

}

在调用的时候返回的是求和函数

箭头函数

x=>x*x            相当于 function(x){return x*x}

如果有多个参数需要定义的时候就为

(x, y) => x * x + y * y

如果有多条执行语句的时候就 

x => {

if (x > 0) {

return x * x;

}

else {

return - x * x;

}

}

如果需要返回一个对象的时候就外加()

x => ({ foo: x })

重点在于,箭头函数内部的this指向是词法作用域,即谁调用,就指向谁,所以使用箭头函数的时候就不用var _this=this;这种提前锁定this指向的写法

ES6

es6新引进了一种数据类型,就是generator;

定义如下:

function* foo(x) {

yield x + 1;

yield x + 2;

return x + 3;

}

在执行的时候,可以返回多个值,但是如果直接调用的话是不会返回所需要的值的,他只是创建了一个generator对象,并没有去执行,调用而言一种是不断的调用该对象的next()方法:next()方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值

var a = foo(5)

a.next();    返回的是{value:6,done:false;}

a.next();    返回的是{value:7,done:false;}

a.next();    返回的是{value:8,done:true;}

在返回的对象中,value代表的是运行一次之后的值,done代表的是这个generator是否完全执行完。

第二种调用方式就是:直接用for...of 调用,这样不用我们自己判断done的值;这种用法不会返回最后自己定义的return的返回值,只会执行yield的操作并返回值。

for (var x of foo(5)) {

console.log(x); // 依次输出6,7

}

浏览器对象

window 表示当前浏览器的窗口,这个对象有innerWidth和innerHeight属性,可以获取浏览器的可视区域的宽高,兼容至ie8。

还有outerWidth和outerHeight获取整个浏览器的窗口宽高。

navigator表示浏览器的信息,最常用的属性:appName浏览器名称,appVersion浏览器版本,language浏览器设置的语言,platform操作系统类型,userAgent浏览器设定的User-Agent字符串。

/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent) ? true : false;判断是否是移动端

screen表示屏幕的信息,常用的属性:width屏幕宽度,height屏幕高度,colorDepth颜色位数

location表示当前页面的url信息。location.href可以获取到完整的url。

加载一个新页面就location.assign(),重新加载调用location.reload()

document表示当前页面,是整个dom树的根节点。document对象有个cookie属性,可以获取到到当前页面的cookie,因此服务器再设置cookie的时候必须使用httpOnly这个选项设定cookie不能被js所读取

history表存了浏览器的历史纪录,js可以调用history的back()和forward()功能就相当于是用户点击了浏览器的后退/前进按钮。由于ajax调用的话,最好是不要使用到history这个东西。

可以使用parentElement.insertBefore(newElement, referenceElement);,子节点会插入到referenceElement之前。

表单

md5 提交的时候:

要想不改变用户的输入,可以利用<input type="hidden">实现:

<!-- HTML --><form id="login-form" method="post" onsubmit="return checkForm()">

<input type="text" id="username" name="username">

<input type="password" id="input-password">

<input type="hidden" id="md5-password" name="password">

<button type="submit">Submit</button></form>

<script>function checkForm() {

var input_pwd = document.getElementById('input-password');

var md5_pwd = document.getElementById('md5-password');

// 把用户输入的明文变为MD5:

md5_pwd.value = toMD5(input_pwd.value);

// 继续下一步:

return true;

}

</script>

用return:true来确定继续提交,如果不符合规定就return false。

操作文件:

当一个表单包含<input type="file">时,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才能正确编码并以multipart/form-data格式发送表单的数据。

对于文件格式的处理,只能靠判断后缀名来处理:

varf = document.getElementById('test-file-upload');

var filename = f.value; // 'C:\fakepath\test.png'if (!filename || !(filename.endsWith('.jpg') || filename.endsWith('.png') || filename.endsWith('.gif'))) {

alert('Can only upload image file.');

return false;

}

h5的file api提供了file 和file reader,下面的代码演示读取用户选取图片并预览。

var

fileInput = document.getElementById('test-image-file'),

info = document.getElementById('test-file-info'),

preview = document.getElementById('test-image-preview');

// 监听change事件:

fileInput.addEventListener('change', function () {

// 清除背景图片:

preview.style.backgroundImage = '';

// 检查文件是否选择:

if (!fileInput.value) {

info.innerHTML = '没有选择文件';

return;

}

// 获取File引用:

var file = fileInput.files[0];

// 获取File信息:

info.innerHTML = '文件: ' + file.name + '<br>' +

'大小: ' + file.size + '<br>' +

'修改: ' + file.lastModifiedDate;

if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {

alert('不是有效的图片文件!');

return;

}

// 读取文件:

var reader = new FileReader();

reader.onload = function(e) {

var

data = e.target.result; // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...'

preview.style.backgroundImage = 'url(' + data + ')';

};

// 以DataURL的形式读取文件:

reader.readAsDataURL(file);

});

ajax:

异步请求

function Ajax(type, url, data, success, failed){

// 创建ajax对象

var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象

// 连接服务器open

if(type == 'GET'){

if(data){

xhr.open('GET', url + '?' + data, true);

} else {

xhr.open('GET', url + '?t=' + random, true);

}

// 发送请求

xhr.send();

} else if(type == 'POST'){

xhr.open('POST', url, true);

// 如果需要像 html 表单那样 POST 数据,请使用 setRequestHeader() 来添加 http 头。

xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

xhr.send(data);

}

// 处理返回数据

request.onreadystatechange = function () { // 状态发生变化时,函数被回调

    if (request.readyState === 4) { // 成功完成

        // 判断响应结果:

        if (request.status === 200) {

            // 成功,通过responseText拿到响应的文本:

            return success(request.responseText);

        } else {

            // 失败,根据响应码判断失败原因:

            return fail(request.status);

        }

    } else {

        // HTTP请求还在继续...

    }

}

原生的看看就行了,用的不多;

判断数据类型:

console.log([].constructor == Array);

console.log({}.constructor == Object);

console.log("string".constructor == String);

console.log((123).constructor == Number);

console.log(true.constructor == Boolean);

或者使用instanceof

(a instanceof Array)   //a是否Array的实例?true or false

(a.constructor == Array)  // a实例所对应的构造函数是否为Array? true or false

以上只能判断当前页面内部定义的东西,如果跨页面调用怎会出错

function isArray(o) {

    returnObject.prototype.toString.call(o) === ‘[object Array]‘;

}

所以判断数组最好是用这个Array.isArray(“。。。”)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容