对象(名词):是指“事物”在程序设计语言中的表现形式。
这里的事物能够是任何东西,咱们能够看到它们具备某些明确特征,能执行某些动做。
这些对象特征就叫作属性(形容词),动做称之为方法(动词)。javascript
类:实际上就是对象的设计蓝图或制做配方。类更多的是一种模板,而对象就是在这些模版的基础上被建立出来的。html
封装:主要阐述对象中包含的内容。一般包括:java
聚合:将几个现有对象合并成一个新对象的过程
继承:实现代码重用
多态:不一样对象经过相同的方法调用来实现各自行为的能力
web
2e+3表示在数字2后面加3个0,即2000ajax
typeof Infinity // number typeof NaN // number typeof null // object null值表示一个空指针对象
Javascript引擎在一个逻辑表达式中遇到一个非布尔类型操做数,
那么该操做数的值就会成为该表达式返回的结果。正则表达式
true || "something" //true true && "something" //"something"
var s = "1s"; //隐式转换Number()用于任何数据类型 s++ //NaN 10 % "0" //NaN 若是被除数是有限大的数值而除数是零,则结果是NaN //乘法口诀程序代码 for(var i=1;i<10;i++){ for(var j=1;j<=i;j++){ document.write(j+"*"+i+"="+i*j+" "); } document.write("<br>"); }
函数内部都有一个内建的arguments数组,能返回函数所接收的全部参数编程
function sumOnSteroids(){ var i,res = 0; for(i = 0; i < arguments.length; i++){ res += arguments[i]; } return res; } sumOnSteroids(1,2,3,4,5,6); //21
var a = 123; function f(){ alert(a); //undefined 这是由于函数域优先于全局域 var a = 1; alert(a); //1 } f();
当咱们将函数B传递给函数A,并由A来执行B时,B就成了一个回调函数json
function A(a,b,c,callback){ var i=0,ar = []; for(i=0;i<3;i++){ ar[i] = callback(arguments[i]*2); } return ar; } function B(a){ //回调函数 return a+1; } A(a,b,c,B)
(function(name){ alert('Hello '+name+' !'); })('Jesse') //Hello Jesse ! //第二对括号起到的是当即调用的做用,同时也是向函数传递参数的地方
使用自调函数的好处是不会产生任何全局变量,缺点是没法重复执行,这使得匿名自调函数最合适于执行一些一次性的或者初始化的任务设计模式
function a(param){ function b(theinput){ //私有函数 return theinput * 2 }; return 'The result is '+b(param) }
使用私有函数的好处:数组
这对于要执行某些一次性初始化工做的函数很是有用
function a(){ alert('A'); //第一次调用该函数时该语句会被执行 a = function(){ //第一次调用时a被赋予新函数 alert('B'); //第二次调用该函数时该语句会被执行 }; } var a = function(){ function someSetup(){ var setup = 'done' } function actualWork(){ alert('work') } someSetup(); return actualWork; }();
在函数内定义的变量在函数外是不可见的,
可是若是该变量是在某个代码块中定义的(if或for语句中),它在代码块外是可见的。
在javascript中每一个函数都有一个属于本身的词法做用域,也就是说每一个函数
在被定义时(而非执行时)都会建立一个属于本身的环境(即做用域)
function f1(){var a = 1;f2();} function f2(){return a;} //f2()被定义时a是不可见的,只能访问自身做用域和全局做用域 f1(); //a is not defined
function f(){ var b = "m"; return function(){ //有着私有做用域,能够访问f()的做用域和全局做用域 return b; } } var n = f(); n(); //m
f()是全局函数,咱们能够将它的返回值赋值给另外一个全局变量,
从而生成一个能够访问f()私有空间的新全局函数
若是一个函数在其父函数返回以后想留住对父级做用域的连接,就必需要为此创建一个闭包
function f(){ var a = []; for(var i = 0; i < 3; i++){ a[i] = function(){ return i; } } return a; } var s = f(); s[0](); //3 s[1](); //3 s[2](); //3
咱们在这里建立了3个闭包,它们都指向一个共同的局部变量i,
可是闭包不会记录它们的值,他们所拥有的只是一个i的引用,
所以只能返回i的当前值(循环结束时i=3).
function f(){ var a = []; for(var i = 0; i < 3; i++){ a[i] = (function(x){ return function(){ return x; } })(i); } return a; } var s = f(); s[0](); //0 s[1](); //1 s[2](); //2
1.十六进制值转为颜色函数getRGB()
function getRGB(hex){ var rgb=[0,0,0]; if(/#(..)(..)(..)/g.test(hex)){ rgb=[parseInt(RegExp.$1,16),parseInt(RegExp.$2,16),parseInt(RegExp.$3,16)]; }; return "rgb("+rgb.join(",")+")"; } getRGB('#00ff00'); //"rgb(0,255,0)"
用[]定义数组的方法咱们称之为数组文本标识法
用{}定义对象的方法咱们称之为对象文本标识法
在javascript中咱们用数组表示索引型数组,用对象表示关联型数组
通常经过如下两种方式访问对象的属性:
function Hero(name){ //构造器函数首字母大写 this.name = name; this.occupation = 'ninja' } var hero = new Hero('jesse'); //使用new操做符建立新对象 hero.name; //ninja
使用构造器函数的好处是能利用同一个构造器函数经过传参从而建立出不一样的对象。
事实上程序所在的宿主环境通常都会为其提供一个全局对象,
而所谓的全局变量其实只不过是该对象的属性
构造器属性其实是一个指向用于建立该对象的构造器函数的引用
hero.contructor //Hero
经过instanceof操做符,咱们能够测试一个对象是否是由某个指定的构造器函数所建立的
hero instanceof Hero; //true
引用类型,由于其值大小不固定,所以栈内存中存放的只是该对象的访问地址,(即该对象的引用)
堆内存为这个值分配空间。所以咱们在引用上所作的任何改动,都会影响到他所引用的源对象。
全部对象都继承自Object对象,所以都具备toLocaleString()、toString()和valueOf()方法。
var o = new Object(); var o = {}; alert(o); //[object,Object]
因为alert()要接收字符串参数,因此它会在后台调用toString()方法
Object构造器的成员:
用Object()构造器所建对象的成员:
var a = new Array(); var a = []; typeof a; //'object' 数组也是对象
值得关注的数组的属性与方法
Array对象的成员:
函数实际上也是一种对象,函数对象的内建构造器是Function()
定义函数的三种方式:
function sum(a,b){return a + b;}; //函数声明
var sum = function(a,b){return a + b;}; //函数表达式
var sum = new Function('a','b','return a + b;'); //Function构造器 避免使用
function A(){return A.caller;} function B(){return A();} B(); //function B(){return A();}
Function对象继承自Object对象,默认拥有Object对象的全部方法
call()、apply()方法都能让对象去借用其余对象中的方法为己所用,这也是一种代码重用的方式。
var someObj = { name: 'Ninja', say: function(who){ return 'Hello '+who+', my name is '+ this.name; } }; var myObj = { name:'Jesse' }; someObj.say.call(myObj, 'Dude');//"Hello Dude, my name is Jesse" //当say()被调用时其中的this就被自动设置成myObj对象的引用
若是咱们调用call方法时须要传递更多的参数,能够在后面依次加入他们
someObj.say.call(myObj,'a','b','c')
若是咱们没有将对象传递给call()的首参数,或者传递的是null,则它的调用对象默认为全局对象
someObj.say.apply(myObj,['a','b','c'])
(function(count){ if(count < 5){ console.log(count); arguments.callee(++count); } })(1) //1,2,3,4
Function对象的成员
var b = new Boolean(); typeof b; //'object' typeof b.valueOf();// 'boolean'
Number对象的toString()方法有一个可选的radix参数(默认10)
var n =new Number(255); n.toString(16); // 'ff'
Number()构造器的成员
Number对象的成员
当咱们将一个基本字符串当作对象来使用时,后台会执行相应的String对象建立操做
String()构造器的成员
String对象的成员
Math对象既不能当作通常函数来使用,也不能用new操做符建立对象,只是一个包含一系列方法和属性的内建对象
获取某个max和min之间的值,公式((max-min)*Math.random())+min
Math对象的成员
Date()构造器成员
Date对象的成员
var reg = new RegExp('j.*t'); var reg = /j.*t/; //匹配任何以j开头t结尾的字符串,且这俩字符之间包含1个或多个字符
var reg = /j.*t/img;
/j.*t/i.test('Javascript') //true /j.*t/i.exec('Javascript')[0] //Javascript
var s = new String('HelloJavascriptWorld'); s.match(/j.*a/ig); //['Java'] s.search(/j.*a/i); //5 //当某个匹配对象被找到时,若是咱们想让相关的替换字符串中包含匹配的文本,可使用$&修饰符 s.replace(/[A-Z]/g,'_$&'); //"_Hello_Javascript_World" //若是正则表达式分了组(即带括号),那么能够用$1表明匹配分组中的第一组,$2表明第二组 s.replace(/[A-Z]/g,'_$1'); //"_Hello_Javascript_World" var csv = 'one, two,three ,four'; csv.split(/\s*,\s*/) //["one", "two", "three", "four"] // \s*匹配0个或多个空格 //以上的4个方法能够接受的参数也包括字符串 "test".replace('t','r'); //"rest"
RegExp对象的成员
try{ //可能会致使错误的代码 }catch(e){ //在发生错误时处理代码 }finally{ //可选的 //不管如何都会执行的代码 }
c = [1,2,[1,2]]; c.sort(); //[1, [1,2], 2]
四、在String()构造器不存在时,自定义MyString()构造器函数并经过如下测试
function MyString(string){ //this.length = this.toString = function(){ return string.toString(); } this.valueOf = function(){ return string.valueOf(); } this.reverse = function(){ return Array.prototype.reverse.apply(string.split('')).join(''); } } var s = new MyString('hello'); s.length; //5 s[0]; //'h' s.toString(); //'hello' s.valueOf(); //'hello' s.chatAt(1); //'e' s.concat(' world!'); //'hello world!' s.slice(0,-1); //'hell' s.split('l'); //['he','','o']
六、在Array()不存在时,建立MyArray()构造器并经过如下测试
var a = new MyArray(1,2,3,'test'); a.length;//4 a.toString();//'1,2,3,test' a[a.length - 1];//'test' a.push('boo');//5 a.pop();//'1,2,3,test' a.join(',');//'1,2,3,test' function MyArray(){ this.length = }
若是在一个对象自身属性中没有找到指定的属性,就能够去原型链中查找相关属性。可是若是赶上对象自身属性与原型链属性同名时,那么对象自身属性的优先级高于原型链属性。
function Gadget(name,color){ this.name = name; this.color = color; this.method =function(){ return 1; } } Gadget.prototype.price = 10; Gadget.prototype.rating = 3; var newtoy = new Gadget('webcam','back'); for(var prop in newtoy){ console.log(prop + '=' + newtoy[prop]); } //name=webcam //color=back //method=function (){return 1;} //price=10 //rating=3
hasOwnProperty()方法用于区分对象自身属性(返回true)与原型属性(返回false)
newtoy.hasOwnProperty('name'); //true newtoy.hasOwnProperty('price'); //false
propertyIsEnumerable()方法对全部非内建对象属性返回true,表示可经过for-in枚举;
newtoy.propertyIsEnumerable('name'); //true
isPrototypeOf()方法会告诉咱们当前对象是不是另外一个对象的原型
var monkey = { hair:true, feeds:'bananas', breathes:'air' }; function Human(name){ this.name = name; } Human.prototype = monkey; var jesse = new Human('Jesse'); monkey.isPrototypeOf(jesse); //true
为Array对象添加inArray()方法,用于查询数组中是否存在某个特定的值
if(!Array.prototype.inArray){ //若是想经过原型为某个对象添加新属性,请务必检查该属性是否已存在 Array.prototype.inArray = function (needle){ for(var i = 0;i < this.length; i++){ if(this[i] == needle){ return true; } } return false; } } var a = ['a','b','c']; a.inArray('d'); //false
为String对象添加reverse()方法,用于反向输出该字符串
if(!String.prototype.reverse){ //若是想经过原型为某个对象添加新属性,请务必检查该属性是否已存在 String.prototype.reverse = function(){ return Array.prototype.reverse.apply(this.split('')).join(''); } } "Jesse".reverse(); //"esseJ" //首先利用this.split('')将目标字符串转为数组,并做为apply()的第二个参数,第一个参数不传值时默认为全局对象 //再调用数组的reverse()方法生成反向数组 //最后经过join()方法将数组转化为字符串
解决方法:当咱们重写某对象的prototype时,必须重置相应的constructor属性
var shape = { type:"triangle", getType:function(){ return this.type; } } function Triangle(a,b,c){ this.a = a; this.b = b; this.c = c; } Triangle.prototype = shape; //当咱们重写某对象的prototype时,必须重置相应的constructor属性 Triangle.prototype.constructor = Triangle; Triangle.prototype.getPerimeter = function(){ return this.a + this.b + this.c; } var t = new Triangle(1,2,3); for(var prop in t){ if(t.hasOwnProperty(prop)){ console.log(prop + '=' + t[prop]); } } t.constructor; //Trianle(a,b,c) shape.isPrototypeOf(t); //true t.getPerimeter(); //6 t.getType(); //"triangle"
function Shape(){ this.name = 'shape'; this.toString = function(){return this.name;}; } function TwoDShape(){ this.name = '2D shape'; } function Triangle(side,height){ this.name = 'Triangle'; this.side = side; this.height = height; this.getArea = function(){ return this.side*this.height/2; } } TwoDShape.prototype = new Shape(); Triangle.prototype = new TwoDShape(); //咱们用构造器Shape()另建了一个新的实体,而后用它去覆盖该对象的原型 //这确保了在继承实现以后,咱们对Shape()所进行的任何修改、重写、删除都不会对TwoShape()产生影响 TwoDShape.prototype.constructor = TwoDShape; Triangle.prototype.constructor = Triangle; var my = new Triangle(5,10); my.getArea();//25 my.toString(); // Triangle
function Shape(){}; Shape.prototype.name = 'shape'; Shape.prototype.toString = function(){return this.name;}; function TwoDShape(){}; TwoDShape.prototype = new Shape(); TwoDShape.prototype.constructor = TwoDShape; //咱们须要在对原型对象进行扩展以前,先完成相关继承关系的构建 TwoDShape.prototype.name = '2D shape'; function Triangle(side,height){ this.side = side; this.height = height; } Triangle.prototype = new TwoDShape(); Triangle.prototype.constructor = Triangle; Triangle.prototype.name = 'Triangle'; Triangle.prototype.getArea = function(){ return this.side*this.height/2; }
function Shape(){}; Shape.prototype.name = 'shape'; Shape.prototype.toString = function(){return this.name;}; function TwoDShape(){}; //TwoDShape.prototype = new Shape(); new Shape()会将Shape的属性设定为对象自身属性,这样的代码是不可重用的 TwoDShape.prototype = Shape.prototype; TwoDShape.prototype.constructor = TwoDShape; TwoDShape.prototype.name = '2D shape'; function Triangle(side,height){ this.side = side; this.height = height; } Triangle.prototype = TwoDShape.prototype; //这样当然能够提升效率,可是子对象和父对象都指向同一对象,一旦对原型属性进行修改,继承的对象相关属性也随之改变 Triangle.prototype.constructor = Triangle; Triangle.prototype.name = 'Triangle'; Triangle.prototype.getArea = function(){ return this.side*this.height/2; } var s = new Shape(); s.name;//"Triangle"
在构建继承关系的过程当中引入一个uber属性,并令其指向其父级原型对象
当对象类型的属性拷贝时,实际上拷贝的只是该对象在内存中的位置指针,这一过程就是浅拷贝
//浅拷贝 function extendCopy(p){ var c = {}; for(var i in p){ c[i] = p[i]; } c.uber = p; return c; } //深拷贝 function deepCopy(p,c){ var c = c || {}; for(var i in p){ if(typeof p[i] === 'object'){ c[i] = (p[i].constructor == Array) ? [] : {}; deepCopy(p[i],c[i]); //在遇到一个对象引用型的属性时,须要再次调用深拷贝 }else{ c[i] = p[i]; } } return c; } var parent = { numbers:[1,2,3], letters:['a','b','c'], obj:{prop:1}, bool:true }; var mydeep = deepCopy(parent); var myshallow = extendCopy(parent); mydeep.numbers.push(4,5,6); //6 mydeep.numbers; //[1, 2, 3, 4, 5, 6] parent.numbers; //[1, 2, 3] myshallow.numbers.push(10); //4 myshallow.numbers; //[1, 2, 3, 10] parent.numbers; //[1, 2, 3, 10] mydeep.numbers; //[1, 2, 3, 4, 5, 6]
基于在对象之间直接构建继承关系的理念,能够用object()来接收父对象,并返回一个以该父对象为原型的
新对象。
function object(p){ function F(){}; F.prototype = p; return new F(); }
var twoD = { name:'2d shape', dimensions:2 } function triangle(s,h){ var that = object(twoD);//把twoD对象全属性拷贝进that对象 that.name = 'Triangle'; that.getArea = function(){return this.side * this.height / 2}; that.side = s; that.height = h; return that; }
实现继承的方法大体上分为两类:
未完成
window.open('新URL','新窗口名','以逗号分割的功能性列表') window.close(); window.moveTo(x,y); window.moveBy(x,y); window.resizeTo(x,y); window.resizeBy(x,y); window.alert(); window.prompt(); //点击确认返回相应文本,点击取消返回null window.confirm();//点击确认返回true,点击取消返回false window.setTimeout();//指定多长时间后执行代码 window.setInterval();//指定每隔多长时间执行代码
navigation.userAgent是一个用户浏览器识别的长字符串,但不要过度依赖这种用户代理字符串,
浏览器能力检测是更好地选择
localtion对象的完整属性:
location对象的方法:
history.forward();history.back();
screen.width(); screen.availwidth();
hasChildNodes()方法用于判断一个节点是否存在子节点 hasAttributes()方法用于检查该元素中书否存在属性 document.documentElement.childNodes.length; //2 //任何节点均可以经过自身的parentNode来访问它的父节点 document.documentElement.parentNode; //<html> document.getElementsByTagName(); document.getElementsByName(); document.getElementById(); nextSibling/previousSibling; firstChild/lastChild
createElement(); var myp = document.createElement('p'); createTextNode();//新建文本节点 appendChild(); document.body.appendChild(myp); cloneNode(true)//true深拷贝 false浅拷贝 insertBefore(要插入的节点,参照节点); replaceChild(要插入的节点,要替换的节点) removeChild(要移除的节点);
addEventListener('事件类型',函数指针[,false]); removeEventListener('事件类型',函数指针[,false]); //匿名函数所定义的监听器是不能被移除的
该方法基于某一节点对象来调用,第三个参数决定代码是否采用事件捕捉,可选的,为了适应更多的浏览器,咱们通常将其设置为false,即采用事件冒泡。
//建立xhr对象 var xhr; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP") } //设置一个能触发readystatechange事件的事件监听器,及处理响应程序 xhr.onreadystatechange=function(){ if (xhr.readyState==4 && xhr.status==200){ console.log(xhr.responseText); } } //open(请求类型,请求目标URL,是否异步请求) xhr.open('GET','somefile.txt',true); //发送请求 xhr.send('')
2.3 function include(js){ var script = document.createElement('script'); script.src = js; document.body.appendChild(script); } include('somescript.js'); 3.1 var myevent = { addListener:function(el,type,fn){ if(typeof window.addEventListener === 'function'){ myevent.addListener = function(el,type,fn){ el.addEventListener(type,fn,false); }; }else if(typeof window.attachEvent === 'function'){ //code for IE myevent.addListener = function(el,type,fn){ el.attachEvent('on'+type,fn); }; }else{ // code for older browsers myevent.addListener = function(el,type,fn){ el['on' + type] = fn; }; } myevent.addListener(el,type,fn); }, removeListener : function(el,type,fn){ if(typeof window.removeEventListener === 'function'){ myevent.removeListener = function(el,type,fn){ el.removeEventEventListener(type,fn,false); }; }else if(typeof window.detachEvent === 'function'){ //code for IE myevent.removeListener = function(el,type,fn){ el.detachEvent('on'+type,fn); }; }else{ // code for older browsers myevent.removeListener = function(el,type,fn){ el['on' + type] = null; }; } myevent.removeListener(el,type,fn); }, getEvent:function(event){}, getTarget:function(event){}, stopPropagation:function(event){}, preventDefault:function(event){} } 4.1 var ajax ={ request:function(url,requestType,queryString){ var xhr; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHTTP") } xhr.onreadystatechange = function(){ if (xhr.readyState == 4 && xhr.status == 200){ console.log(xhr.responseText); } } xhr.open(requestType,url,true); xhr.send(''); } } ajax.request('some.txt','get');
为了减小命名冲突,最好的办法是将变量和方法定义在不一样的命名空间中,这种方法的实质是只定义一个全局变量,
并将其余的方法和属性定义为该变量的属性。
var mySpace = {}; mySpace.event = { addListener:null, removeListener:null …… } if(typeof window.addEventListener === 'function'){ mySpace.event.addListener = function(el,type,fn){ el.addEventListener(type,fn,false); }; mySpace.event.removeListener = function(el,type,fn){ el.removeEventListener(type,fn,false); }; }else if(typeof window.attachEvent === 'function'){ //code for IE mySpace.event.addListener = function(el,type,fn){ el.attachEvent('on'+type,fn); }; mySpace.event.removeListener = function(el,type,fn){ el.detachEvent('on'+type,fn); }; }else{ // code for older browsers mySpace.event.addListener = function(el,type,fn){ el['on' + type] = fn; }; mySpace.event.removeListener = function(el,type,fn){ el['on' + type] = null; }; }
var mySpace = {}; mySpace.event = { addListener:function(el,type,fn){ if(typeof window.addEventListener === 'function'){ mySpace.event.addListener = function(el,type,fn){ el.addEventListener(type,fn,false); }; }else if(typeof window.attachEvent === 'function'){ //code for IE mySpace.event.addListener = function(el,type,fn){ el.attachEvent('on'+type,fn); }; }else{ // code for older browsers mySpace.event.addListener = function(el,type,fn){ el['on' + type] = fn; }; } mySpace.event.addListener(el,type,fn); } };
该模式适用于有不少参数的函数或方法
用单个对象来替代多个参数有如下几点优点:
var myapp = {}; myapp.dom = {}; myapp.dom.Button = function(text,conf){ var type = conf.type || 'submit'; var font = conf.font || 'microsoftyahei'; //…… } //使用方法以下: var config = { font:'Arial,Verdana,microsoftyahei', color:'#fff' }; new myapp.dom.Button('lalala',config);
(function(){ // code in here })() //该模式特写适用于某些脚本加载时所执行的一次性初始化工做
构造器返回的是新建对象的this指针,咱们可使用这些方法所返回的实例来调用其余方法
document.body.appendChild( new mySpace.dom.Element('span') .setText('hello') .setStyle('color','red') );
var obj = JSON.parse(xhr.responseText);