JQ对象与DOM对象区分。JQ对象用JQ的方法,DOM对象用DOM方法。不能互用。
window.onload()是在建完DOM树之后,也是在所有图像和其他外部资源完整加载并在浏览窗口显示完毕之后,才执行。所以当某个资源要加载很久,会一直等待。只能在页面绑定一个。
而jQuery的$(document).ready(function()),是在建完DOM树之后,就执行了。可以在页面绑定多个。
jq对象与DOM对象互转。jq转DOM,用下标就可以。DOM转jq,用$()
括起来就可以。
多个库共用有$
有冲突时,用以下方法解决冲突:
var $j = jQuery.noConflict();//自定义一个快捷方式。jQuery依旧可用,$不再是jQuery的快捷方式
$('')
获取的永远是对象,即使dom中没有这个元素,判断是否存在用.length > 0
来判断
jq中的方法很多都可以读取值和设置值。通常括号里不填参数,则读取第一个匹配元素的值;括号里填参数则设置所有匹配元素的值。
//基本选择器
$('#id')//id
$('element')//ele
$('.class')//class
$('*') //所有元素
$('selector,selector')//多个选择器,逗号分隔;
//关系选择器
$('sel sel')//后代选择器
$('parent>child')//子代选择器
$('pre+next')//相邻兄弟选择器
$('pre~siblings')//后面兄弟选择器
//关系选择器替代方法,括号内可以再写选择器
.children()//子元素
.parent()//父元素
.parents()//祖先元素
.next()//下一个相邻兄弟
.nextAll()//后面所有相邻兄弟
.prev()//前一个相邻兄弟
.prevAll()//前面的所有兄弟
.siblings()//所有兄弟
//过滤选择器
//基本过滤选择器
:first//匹配找到的第一个元素
:last//匹配找到的最后一个元素
:not(sel)//匹配找到的除去not中的元素剩下的元素
:even//匹配找到的索引为偶数的元素、从0开始
:odd//匹配索引为奇数的元素,索引从0开始
:eq(index)//匹配指定索引值的元素
:gt(index)//匹配大于指定索引值的元素
:lt(index)//匹配小于指定索引值的元素
:animated// $(':animated')//匹配正在执行动画效果的元素
:focus//选取当前猎取焦点的元素。
//例如:只对不在执行动画效果的元素执行一个动画特效:
$("#run").click(function(){
$("div:not(:animated)").animate({ left: "+=20" }, 1000);
});
//子元素过滤选择器
:nth-child(index/even/odd/eq)//与css的用法相似,index从 1 算起
:first-child :last-child :only-child
//内容过滤选择器
:contains('我们')//过滤选择器
:eq(i)//i从0算起,可以用于过滤jq匹配的元素集合
:empty//选择不包含子元素或文本的元素
:has(sel)//选择包含sel元素的元素
:parent//选择有子元素或文本的元素
:hidden//选择所有不可见的元素
:visible//选择所有可见的元素
//属性过滤选择器
[attribute]//选取拥有此属性的元素
[attribute="value"]//选取属性值为value的元素
!="value"//值不等value
^="value"//值以value开始
$="value"//值以value结束
*="value"//值含有value
|="value"//值等于value或以它为前缀(该字符串后跟一个连字符“-”)的元素
~="value"//选择属性用空格的值中包含一个给定值的元素
[attri][attri][attri]//满足多个条件
//表单对象属性过滤选择器
:enabled//选择所有可用的元素
:disabled//选择所有不可用的元素
:checked//选取所有被选中的元素(单选,多选)
:selected//选择所有被选中的选项元素(下拉列表)
//表单选择器
:input //匹配所有input, textarea, select button元素
:text //匹配所有单行文本框
:radio //所有单选
:checkbox //所有复选
:submit //所有提交按钮
:button //所有按钮
:reset //所有重置按钮
:image //所有图像按钮
:password //所有密码框
Javascript语言的执行环境是”单线程”(single thread)。所谓”单线程”,就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。 为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
通常用ajax来实现异步请求。
在现代浏览器上写Ajax主要是依靠XMLHttpRequest
对象:
function success(data){
console.log(data);
}
function error(status){
console.log(status);
}
var request;
if (window.XMLHttpRequest) {
request = new XMLHttpRequest(); //新建XMLHttpRequest对象
} else {
request = new ActiveXObject('Microsoft.XMLHTTP');//兼容ie5,ie6
}
request.onreadystatechange = function () { //状态发生变化时,函数被回调
if (request.readyState === 4) { // 请求完成
//判断响应结果:
if (request.state === 200) { //成功通过responseText拿到响应文本
return success(request.responseText);
} else {
//失败,根据响应码判断失败原因
return error(request.status);
}
} else {
//HTTP请求还在继续...
}
};
request.open('GET', '/api/categories');
request.send();
open(‘method’, url, true/ false),第三个参数默认是true(异步),一般不填
send(data),get方法发送的数据写在url里,send()中一般不填,post方法,则填请求的数据。
由于浏览器的同源策略。默认情况下,JavaScript在发送Ajax请求时,url 的域名必须和当前页面完全一致。
完全一致是指:
www.example.com
和example.com
不同)http
和https
不同):80
端口,它和:8080
不同,与其它端口也不同),有点浏览器允许端口不同,大部分浏览器不允许但有些时候我们就是需要跨域请求资源,怎么办呢?
通常使用的方法有以下几种:
第一种:JSONP,它有个限制,只能用GET请求,并且要求返回JavaScript。这种方式跨域实际是利用了浏览器允许跨域引用JavaScript资源。
第二种:CORS,它是对方服务器给你所在域设置了Access-Control-Allow-Origin
,你的请求才会成功。而且需要浏览器支持HTML5。
第三种:代理服务器。
let
声明一个块级作用域变量。
const
声明一个常量,也具有块级作用域。
解构赋值,就是同时对一组变量进行赋值。可以是数组,也可以是对象。
对数组元素进行解构赋值:
let [x,y,z] = [3,4,5];
从一个对象中取出若干属性,使用解构赋值:
let person = {
name:'xiaowang',
age:11,
birthday:'May 1st'
}
let {name,birthday} = person;
console.log(name + '\'s ' + 'birthday is ' + birthday);
交换变量的值
let x = 1,y = 2;
[x,y] = [y,x];
快速获取当前页面的域名和路径
let {hostname:domain, pathname:path} = location;
如果一个函数接收一个对象作为参数,那么,可以使用解构直接把对象的属性绑定到变量中。例如,下面的函数可以快速创建一个Date
对象:
function buildDate({year, month, day, hour=0, minute=0, second=0}) {
return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}
它的方便之处在于传入的对象只需要year
、month
和day
这三个属性:
buildDate({ year: 2017, month: 1, day: 1 });
// Sun Jan 01 2017 00:00:00 GMT+0800 (CST)
注:解构赋值的目的主要目的是解少代码量,顺便让代码更易读。
window对象不但充当全局作用域,而且也表示浏览器窗口。
//获取浏览器窗口的内部宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高。
window.innerWith
window.innerHeight
//获取浏览器窗口整个窗口的宽高。
window.outerWith
window.outerHeight
navigator对象表示浏览器的信息,最常用的属性包括:
navigator.appName//浏览器名称;
navigator.appVersion//浏览器版本;
navigator.language//浏览器设置的语言;
navigator.platform//操作系统类型;
navigator.userAgent//浏览器设定的User-Agent字符串。
注意:navigator的信息可以很容易地被用户修改,所以JavaScript读取的值不一定是正确的。
JavaScript 面向对象编程,主要就是搞清楚原型继承的问题。下面举两个例子说明一下:
//创建父类
var Book = function(props){
this.name = props.name || '书';
this.year = props.year || 0;
this.author = props.author || '侠名';
}
//在原型上定义共享函数
Book.prototype.sayName = function(){
console.log( this.name );
}
//创建子类
var StoryBook = function(props){
Book.call(this, props);//"继承"构造函数 Book
this.kind = 'StoryBook';
this.pages = props.pages || 0;
}
//继承函数
var inherits = function(Child,Parent){
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
//继承
inherits(StoryBook,Book);//继承父类
//创建实例
var book_theThreeKingdoms = new StoryBook({name:'三国演义'});
console.log( book_theThreeKingdoms.name );//三国演义
ES6 中的 class
实现继承,class
的方式实现继承,和上面的方法实际上是一样的,只不过通过class
大大简化操作,也让代码更易读。
//创建父类,定义共享函数
class Book{
//构造函数
constructor(props){
this.name = props.name || '书';
this.year = props.year || 0;
this.author = props.author || '侠名';
}
//共享函数
sayName(){
console.log( this.name );
}
}
//创建子类,继承父类
class StoryBook extends Book{
constructor(props){
super(props);//调用父类的构造方法
this.kind = 'StoryBook';
this.pages = props.pages || 0;
}
}
//创建实例
var book_theThreeKingdoms = new StoryBook({name:'三国演义'});
console.log( book_theThreeKingdoms.name );//三国演义
原型链继承,就是为了方便实例继承原型中的属性和方法,不重复写同样的代码。
要理解原型链的继承,首先要理解 构造函数、原型、实例 这三者之间的关系。
举个例子:
const Cat = function (name,age) {
this.name = name;
this.age = age;
};//构造函数
Cat.prototype.sayName = function () {
console.log(this.name);
};//原型
const cat1 = new Cat('叮当',2);//实例
console.log(cat1 instanceof Cat);//true
cat1.sayName();//实例继承原型中的方法
简单来说,就是构造函数像是一个生产工厂,负责生产实例;
原型就是储存实例共同属性和方法的一个对象,这样就可以让方法,属性重复利用。
构造函数的 prototype
属性指向原型;
原型有一个 constructor
的属性指向构造函数;
实例中有一个 __proto__
的属性指向原型。
__proto__
的引用链被被作原型链。
const Cat = function (kind) {
this.kind = kind;
};
Cat.prototype.sayAge = function () {
console.log(this.age);
};
const Persian = function (name,color,age) {
this.name = name;
this.color = color;
this.age = age;
}
Persian.prototype = new Cat('波斯猫');//让 Persian.prototype 属性指向 Cat 的实例,实现继承。
Persian.prototype.constructor = Persian;//将 constructor 重新指向对应的构造函数
const cat1 = new Persian('叮当','red',10);
cat1.sayAge();//10
console.log(cat1.kind);//波斯猫
有时候我们并不需要继承父类的属性,只需要它的方法。
Persian.prototype = new Cat();
这时候就会多出一个 kind
的属性。这时候我们可以这样
const Cat = function (kind) {
this.kind = kind;
};
Cat.prototype.sayAge = function () {
console.log(this.age);
};
const Persian = function (name,color,age) {
this.name = name;
this.color = color;
this.age = age;
}
Persian.prototype = Object.create(Cat.prototype);//让 Persian.prototype 属性指向 Cat.prototype 新建的实例,实现继承。
Persian.prototype.constructor = Persian;//将 constructor 重新指向对应的构造函数
const cat1 = new Persian('叮当','red',10);
cat1.sayAge();//10
console.log(cat1.kind);//波斯猫
Object.getPrototypeOf(cat1) === Persian.prototype;
一个对象 obj,查找某一个属性或方法时,会先在自身查找,如果找到,就会输出。如果没有找到,就会继续在它的原型上找,如此类推,一直到 Object.prototype.__proto__
-> null
。