前端攻城狮知识体系
要点:对Web标准的理解、浏览器差异、CSS基本功:布局、盒子模型、选择器优先级及使用、HTML5、CSS3、移动端开发技术等
ps. 这些内容之后再看都会变的比较基础简单, 我期待这一天的到来.
,DTD文档模型,声明位于文档中的最前面,处于
标签之前。告知浏览器的解析器,用什么文档类型规范来解析这个文档。a b span img input select strong(强调的语气)
div ul ol li dl dt dd h1 h2 h3 h4 … p
盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border).
p:first-of-type 选择属于其父元素的首个 元素的每个
元素。
p:last-of-type 选择属于其父元素的最后
元素的每个
元素。
p:only-of-type 选择属于其父元素唯一的
元素的每个
元素。
p:only-child 选择属于其父元素的唯一子元素的每个
元素。
p:nth-child(2) 选择属于其父元素的第二个子元素的每个
元素。
:enabled :disabled 控制表单控件的禁用状态。
:checked 单选框或复选框被选中。
给div设置一个宽度,然后添加margin:0 auto属性
div{
width:200px;
margin:0 auto;
}
居中一个浮动元素
确定容器的宽高 宽500 高300 的层
设置层的外边距
div {
Width:500px ; height:300px;//高度可以不设
Margin: -150px 0 0 -250px;
position:relative;相对定位
background-color:pink;//方便看效果
left:50%;
top:50%;
}
使用率较高的框架有jQuery
轻量级框架有Modernizr(理解这些框架的功能、性能、设计原理)
Webstorm , Brackets , Sublime Text , Chrome
编写 CSS、让页面结构更合理化/语义化,提升用户体验,实现良好的页面效果和提升性能。
<header>, <hgroup>, <nav>, <article>, <session>, <aside>和<footer>等
以下是权重的规则:标签的权重为1,class的权重为10,id的权重为100,以下例子是演示各种定义的权重值
/*权重为1*/
div{
}
/*权重为10*/
.class1{
}
/*权重为100*/
#id1{
}
/*权重为100+1=101*/
#id1 div{
}
/*权重为10+1=11*/
.class1 div{
}
/*权重为10+10+1=21*/
.class1 .class2 div{
}
如果权重相同,则最后定义的样式会起作用,但是应该避免这种情况出现
标签的长时间连接(可跨域)要点:数据类型、面向对象、继承、闭包、插件、作用域、跨域、原型链、模块化、自定义事件、异步装载回调、模板引擎、Nodejs等
number, string, boolean, object, null, undefined
Date、Math、Number、Boolean、String、Array、RegExp、Function…
function Person(name, age) {
this.name = name;
this.age = age;
this.sing = function() { alert(this.name) }
}
闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数
if(arr instanceof Array){}
Object.prototype.toString.call(arr))//"[object Array]",结果不受iframe的限制
新创建的对象由 this 所引用,并且最后隐式的返回 this 。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
JSON( JavaScript Object Notation ) 是一种轻量级的数据交换格式。它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小 {'age':'12', 'name':'back'}
defer和async、动态创建DOM方式(用得最多)、按需异步载入js
- defer(H4): 异步加载,DOM解析完成后DOMContentLoaded事件触发之前执行, 注意:script里面不能有document.write的内容
- async(H5: 异步加载,下载完后立即执行!
- 创建script,插入到DOM中,加载完毕后callBack
Ajax: asyn+javascript+and+xml
同步异步的区别在于不阻塞当前进程
jsonp、 iframe、window.name、window.postMessage、服务器上设置代理页面
立即执行函数,不暴露私有成员
var module1 = (function(){
var _count = 0;
var m1 = function(){
//...
};
var m2 = function(){
//...
};
return {
m1 : m1,
m2 : m2
};
})();
它的功能是把对应的字符串解析成JS代码并运行;
避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。
高并发、聊天、实时消息推送
(优点)因为Node是基于事件驱动和无阻塞的,所以非常适合处理并发请求,
因此构建在Node上的代理服务器相比其他技术实现(如Ruby)的服务器表现要好得多。
此外,与Node代理服务器交互的客户端代码是由javascript语言编写的,
因此客户端和服务器端都用同一种语言编写,这是非常美妙的事情。
(缺点)Node是一个相对新的开源项目,所以不太稳定,它总是一直在变,
而且缺少足够多的第三方库支持。看起来,就像是Ruby/Rails当年的样子。
说明白一点其实就是更改对象的内部指针,即改变对象的this指向的内容。
输出:
Object {a: "func"}
a:myfunc
this.a:func
x:var
Object {a: "func"}
call相当于把两个函数的作用域揉在一起了,this指向了call的第一参数(func), 并且不会再给myfunc. 首先, myfunc.call(func,"var")
时,this指针由之前的myfun指向了func,并执行了this.a="func"
; 之后在myfunc继续向下执行var a="myfunc"; console.log("a:"+a);
所以输出a:myfunc; 因为this.a=”func”, 故输出this.a:”func”; x的传入参数是var, 所以输出var.
事实上,apply()和call()并非只用来传递参数,它们真正强大的地方是能够扩充函数赖以运行的作用域。
window.color = "red";
var o = {
color: "blue"
};
function sayColor() {
alert(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
sayColor()
是作为全局函数定义的,当在全局作用域中调用它时,它会显示“red”——因为对this.color的求值会转换成window.color的求值。而sayColor.call(this)和sayColor.call(window),则是两种显式地在全局作用中调用函数的方式,结果当然都会显示“red”。但是,当运行sayColor.call(o)时,函数的执行环境就不一样了,因为此时函数体内的this对象指向了o,于是就显示的是“blue”。
使用call或apply()来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。
jQuery中没有提供这个功能,所以你需要先编写两个jQuery的扩展:
$.fn.stringifyArray = function(array) {
return JSON.stringify(array)
}
$.fn.parseArray = function(array) {
return JSON.parse(array)
}
然后调用:
$("").stringifyArray(array)
原型对象也是普通的对象,是对象一个自带隐式的 __proto__
属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链(prototype chain)。
原型链是一个由对象组成的有限对象链由于实现继承和共享属性。
下面的图示就是表示了上述a,b,c的继承关系
var Calculator = function (decimalDigits, tax) {
this.decimalDigits = decimalDigits;
this.tax = tax;
};
然后,通过给Calculator对象的prototype属性赋值对象字面量来设定Calculator对象的原型。
Calculator.prototype = {
add: function (x, y) {
return x + y;
},
subtract: function (x, y) {
return x - y;
}
};
alert((new Calculator()).add(1, 3));
这样,我们就可以new Calculator对象以后,就可以调用add方法来计算结果了。
第二种方式是,在赋值原型prototype的时候使用function立即执行的表达式来赋值,即如下格式:
Calculator.prototype = function () { } ();
它的好处在前面的帖子里已经知道了,就是可以封装私有的function,通过return的形式暴露出简单的使用名称,以达到public/private的效果,修改后的代码如下:
Calculator.prototype = function () {
add = function (x, y) {
return x + y;
},
subtract = function (x, y) {
return x - y;
}
return {
add: add,
subtract: subtract
}
} ();
alert((new Calculator()).add(11, 3));
同样的方式,我们可以new Calculator对象以后调用add方法来计算结果了。
//创建BaseCaculator对象
var BaseCalculator = function() {
this.decimalDigits = 2;
};
//添加功能-对象
BaseCalculator.prototype = {
add: function(x, y) {
return x + y;
},
subtract: function(x, y) {
return x - y;
}
};
var Calculator = function () {
//为每个实例都声明一个税收数字
this.tax = 5;
};
//继承
Calculator.prototype = new BaseCalculator();
var calc = new Calculator();
alert(calc.add(1, 1));
//BaseCalculator 里声明的decimalDigits属性,在 Calculator里是可以访问到的
alert(calc.decimalDigits);
//覆盖前面Calculator的add() function
Calculator.prototype.add = function (x, y) {
return x + y + this.tax;
};
var calc = new Calculator();
alert(calc.add(1, 1));
当查找一个对象的属性时,JavaScript 会向上遍历原型链,属性在查找的时候是先查找自身的属性,如果没有再查找原型,再没有,再往上走,直到找到给定名称的属性为止,到查找到达原型链的顶部 - 也就是 Object.prototype - 但是仍然没有找到指定的属性,就会返回 undefined
hasOwnProperty是Object.prototype的一个方法, 他能判断一个对象是否包含自定义属性而不是原型链上的属性,因为hasOwnProperty 是 JavaScript 中唯一一个处理属性但是不查找原型链的函数。
如果hasOwnProperty被重写, 使用下面的方法总是保险的:
var foo = {
hasOwnProperty: function() {
return false;
},
bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // 总是返回 false
// 使用{}对象的 hasOwnProperty,并将其上下为设置为foo
{}.hasOwnProperty.call(foo, 'bar'); // true
遍历foo对象, 例举出属于他自己的对象:
Object.prototype.bar2 = 1;
for(var i in foo) {
if ({}.hasOwnProperty.call(foo,i)) {
console.log(i);
}
}
//hasOwnProperty
//bar
不输出bar2.
通常可以做一些小练习来判断TA的水平,js 虽然很灵活,但是具体的代码和实现方式能体现出一个人的全局观,随着代码规模的增长,复杂度增加,如何合理划分模块实现功能和接口的能力比较重要。(下面例题)
1
["1", "2", "3"].map(parseInt)
-> [1, NaN, NaN]//因为parseInt需要两个参数,而map传递了三个,故...
//应该为["1", "2", "3"].map(function(value){return parseInt(value)});
2
[typeof null, null instanceof Object]
->["object", false]
3
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow)] ]
->Math.power(底数,指数),故第一次:Math.power(3,2)=9,第二次:Math.power(9,1)=9.
4
var val = 'smtg';
console.log('Value is ' + (val === 'smtg') ? 'Something' : 'Nothing');
-> Something,先进行字符串拼接,故不管什么值都返回something
5
var name = 'World';
(function(){
if(typeof name === 'undefined'){
var name = "Jack";
console.info('Goodbye '+ name);
}else{
console.info('Hello ' + name);
}
})();
->判断语句被包裹在立即调用函数里,函数内部无法访问外部值为'World'的name,
因此typeof name === 'undefined'为真,执行下一步操作,最终输出Goodbye Jack
6
var START = END -100;
var count = 0;
for(var i = START ; i <= END ;i++){
count ++;
}
console.info(count);
->END = 9007199254740992 ,START = 9007199254740892目的是计算的END和START之间的
差。但是2的53次方计算出的结果由于精度问题使得i++失效。
7
(function(x){
delete x;
alert(x);
})(1+5);
-> 6//delete只能通过for in删除访问的属性, 即使删除失败也不会报错,返回6
HTTP请求流程: