前言
平时的项目中,很少再去写原生的js代码,自己也很少再去思考某些代码在原生情况的书写方法,导致自己忽略了很多原生js中重要的内容。学习其他框架的时候也是只会使用,而对实现原理了解的较少。最近因为某些契机,燃起了巩固js知识的欲望,故分享下最近学习的一些心得体会。
1、数据类型
- 基本数据类型:number,string,boolean,undefined,null
- 复杂数据类型:object
一些相关的内容:- n/a not applicable
- 加法无法进行类型转换,减法可以,+/-0相加减,同号得正,异号得负。
- NaN not a number
- undefined表示一个特殊的值undefined
- null表示一个空指针
- 前置递增或递减会在求值以前执行,称为副效应
- 禁止给undefined、NaN、Infinity赋值
5+"5"="55" string
5-"5"=0 number
-0-(+0)=-0
// true
typeof(null);//object
null==null;
null===null
null==undefined;
undefined==undefined;
undefined===undefined;
// false
NaN==NaN;
2、数组
数组的一些常用方法:
- 栈方法(LIFO): pop、push
- 队列方法(FIFO): shift、unshift
- 排序 sort、reverse
要使数组元素按大小排序可在排序方法中加入函数,如从小到大排序:
var arr=[5,2,8];
arr.sort(function(a,b){
return a-b;
});
- 数组相加: concat
- 迭代方法:
数组的迭代方法不会修改数组。- every() 数组中的每一项都运行给定函数 全为true就是true 否则为false
- filter() 数组中的每一项都运行给定函数 返回结果为true的函数
- forEach() 数组中的每一项都运行给定函数 (IE9+)
- some()对数组中的每一项运行给定函数,如果该函数对任一项返回 true,则返回 true。
- map()对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
具体的实例代码如下:
var numbers=[1,2,3,4,5,5,6,7,8,2,43];
var every=numbers.every(function(item,index,array){
return item>2;
});
console.log(every); //false
var filter =numbers.filter(function(item,index){
return item==index;
});
console.log(filter); //[5,6,7,8]
var foreach=numbers.forEach(function(item,index){
item+=1;
});
console.log(foreach); //undefined
var some=numbers.some(function(item,index){
return item>index+50;
});
console.log('some='+some); //some=false
var map=numbers.map(function(item,index){
return item*2;
});
console.log(map); //[2, 4, 6, 8, 10, 10, 12, 14, 16, 4, 86]
var sum=numbers.reduce(function(prev,next,index){
return prev+next;
});
console.log(sum); //86
3、DOM
文档对象模型(document object model),这是一个api,描绘了一个层次化的节点树,用于增加,删除,修改页面的某一部分。DOM有level1,level2,level3三级,DOM事件有0级,2级,以及三级事件。
- 获取子节点:childNodes
- 获取父节点:parentNode
- 兄弟节点:previousSibiling(前面)、nextSibling(后面)
- 获取当前URL:URL
- 获取来源URL:referrer
获取元素的一些方法:
- 文档元素表示
<html>
也是页面的根元素 - 通过ID获取,标签名获取
- anchors 返回对文档中所有anchor对象的引用,如
<a href="#" onclick="change()" id="test" name="test">test</a>
<script>
console.log(document.anchors);
//[a#test, test: a#test]
//length:1
</script>
- 获取页面所有表单元素: forms
- 获取页面所有图片元素:images
- 获取页面所有链接元素:links
- 获取元素的标签名:tagName
- 元素的属性:getAttribute,setAttribute,removeAttribute、createAttribute (不支持IE6)
- 创建元素:createElement
- nodeType,nodeName,nodeValue
节点类型 | nodeType | nodeName | nodeValue |
---|---|---|---|
element | 1 | 元素名 | null |
attr | 2 | 属性名 | 属性值 |
text | 3 | #text | 节点内容 |
comment | 8 | #comment | 注释文本 |
document | 9 | #document | null |
DOM的扩展
- querySelector()/querySelectorAll()
- html5新增dom方法
- getElementsByClassName
- htmlDocument:readyState有两种状态 loading以及complete
- 自定义数据属性 data-
- 获取内容 innerHTML,outerHTML
- IE8以下不支持事件流(事件冒泡,事件捕获)。javascirpt与HTML之间的交互是通过事件实现的。IE的事件流叫做事件冒泡,即事件开始时由最具体的元素逐级向上传播至不具体的元素。如下:
<body onclick="bodyClick()">
test1
<a href="#" onclick="change()" id="test" name="test">test</a>
</body>
<script>
function bodyClick(){
alert(1);
}
function change(){
alert(0);
}
</script>
点击a链接的结果是,先弹出0,再弹出1。
事件捕获则是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
4、BOM
浏览器对象模型(browser object model),提供了很多对象,用于访问浏览器的功能,核心是window,它是浏览器的一个实例。
- 打开关闭窗口: open/close
- 系统对话框:alert/confirm/prompt
- 打印:print
- 获取窗口位置: window.screenLeft/Top 表示窗口相对于屏幕的位置
- 窗口移动:moveTo/moveBy
- 窗口大小:resizeTo/resizeBy
- 打开原始窗口对象:openr
- 前进后退:history.go()/back()/forward()
5、创建对象
对象的定义:无序属性的集合,函数也是对象。
a. 工厂模式,用函数来封装以特定接口创建对象的细节。如下:
function factory(name,number,score){
var o=new Object();
o.name=name;
o.number=number;
o.score=score;
return o;
}
var obj = new factory('leo',1,60);
b.构造函数。创建一个新对象,将构造函数的作用域赋给新对象(this),执行构造函数中的代码,最后返回新对象。如下:
function Student(name,number,score){
this.name=name;
this.number=number;
this.score=score;
this.outPut=function(){
console.log('name:'+this.name+'
number:'+this.number+'
score:'+score);
}
}
var yu=new Student('monkey',1001,99);
构造函数始终都应该以大写字母开头.
c.原型模式。所有的函数都有一个原型(prototype)属性,通过将信息添加到原型对象中去,让所有新建的对象实例共享这些信息。
function Person(){
}
Person.prototype.name='300kuai';
Person.prototype.number=38;
Person.prototype.score=59;
Person.prototype.outPut=function(){
console.log('name:'+this.name+'
number:'+this.number+'
score:'+this.score);
}
var person1=new Person();
d.自定义类型。组合使用构造函数模式和原型模式。构造函数用于定义实例属性,原型用于定义方法和共享属性。这也是使用最多的一种方法。
- 对象的遍历:
1.for-in。
var obj={'first':'leo','second':'monkey'};
for (var prop in obj) {
console.log(
obj[prop]
);
}
6、函数
- 函数声明提升,即执行代码之前会先读取函数声明。如以下代码是正确的。
console.log(sumFunc(10,10));
function sumFunc(){
var sum=0;
for( var i in arguments){
sum+=arguments[i];
}
return sum;
}
但是,如果将函数赋给变量,函数没有函数名,是匿名函数,必须先赋值。如下面代码就是错误的:
console.log(sumFunc(10,10));
var sumFunc=function(){
var sum=0;
for( var i in arguments){
sum+=arguments[i];
}
return sum;
}
总结
从事前端工作越久,使用的框架,方案越多,越发现,其实最基础的还是最重要的。不管框架多么酷炫,实现的功能多么强大,始终只是我们编程的一种工具。当然,虽然这些工具不是不可或缺的,但是,掌握这些框架知识对我们项目模块化的开发,软件性能的提高确实起到了重要的作用。
又看了一遍最基础的javascirpt,对于原型,闭包,继承的理解还是不是非常深刻,接下去的几天也打算重点看下这些内容,下一篇文章也应该是这几个内容。