javascript学习笔记
书籍
javascript语言精髓与编程实践
第一讲
javascript是一种解释执行语言(边解释边执行)
浏览器对象window
文档对象document
控制台对象console
javascript的属性type src defer charset
第二讲
2.1 变量--javascript是一种弱类型的脚本语言,变量名区分大小写
全局变量和局部变量之间的差别
基本数据类型(根据赋值决定的变量类型)
number: Integer Float(最高精度是17位) NaN Infinity,数值类型还可以以8进制和16进制来进行表示
boolean:
String:
undefined: 变量申明但未赋值
null:表示一个空的对象引用 它是一个对象类型
引用数据类型
Object(Array Date Object )
2.2 运算符
== 和 === 之间的差别
== 表示 可以经过自动转换 比较的是数值
=== 表示 可以经过自动转换 比较的是数值和数据类型
支持三目运算符
执行语句基本上和java相似
第三讲 引用类型
3.1 数组是引用类型
js数组类似于java中的容器,元素类型可以不同,长度可变。
var arr = []//比较推荐这种方式
var result = arr.push();通过这种方式像数组中追加元素,返回值是新数组的长度
var result = arr.pop();//从数组的尾部移除一个元素,返回值是移除的元素
var result = arr.shift();//从数组的头部移除一个元素,返回值是移动的元素
var result = arr.unshift(10,true);//从数组的头部插入元素,返回值是数组的长度
var result = arr.slice(2, 4);//从数组中截取,左闭右开区间
arr.sort(function(){});可以传递一个function,这个function定义了排序的方式
var arr = new Array();//这种方式并不推荐
3.2 对象Object
var obj = {}
var obj = new Object();//这种方式 不推荐使用
obj.age = 19;
obj["age"] = 19;对象属性赋值方式存在两种
delete obj.age;
delete obj.say; 删除对象中的属性或者方法
遍历一个js对象
for in 进行遍历
for(var attribute in obj) {
alert(obj[attribute]);//此处获取值只能使用中括号
}
constructor返回创建构造函数的内容
hasOwnProperty()判断对象中是否存在某个属性
function Map() {
var obj = {};
this.put = function(key, value) {
obj[key] = value;
}
this.size = function() {
var count = 0;
for (var attr in obj) {
count ++;
}
return count;
}
this.get = function(key) {
if (obj.hasOwnProperty(key)) {
return obj[key];
}
}
this.delete = function(key) {
if (obj.hasOwnProperty(key)) {
delete obj[key];
}
}
this.eachMap = function(fn) {
for (var attr in obj) {
fn(attr, obj[attr]);
}
}
}
var map = new Map();
map.eachMap(function(key, value) {
alert(key + " : "+ value);
})
利用js对象特性实现去除数组中重复项
js中key具有唯一性
3.3 其他引用类型对象
单体对象 Global对象 encodeURI(), decodeURI() eval(string) javascript解析器,将字符串解析成脚本 eval('(' + str + ')')、
Math
Date
函数
正则表达式
第四讲 函数
函数也是一种数据类型,在js中函数是可以嵌套定义的,但是,最好不要这么做,因为这违反了代码结构一致性原则
无返回值类型,参数列表也无类型,相当于函数入口,return相当于函数出口,
函数三种定义方式 js中不存在重载
1 function语句//这是一种静态的方式,优先解析 占用内存,效率较高 这是一种全局变量的形式 先进行解析放入内存 函数作用域
2 函数直接量//这是比较推荐的一种方式//这是一种静态的方式 顺序解析 占用内存 效率较高 先声明后赋值,因此是一种局部变量的形式 函数作用域
3 function构造函数式 var test = new Function("a", "b", "return a + b;");//这是一种动态的方式进行的 顺序解析,这种方式效率不高,但是不占用内存 全局作用域
函数参数
js中形参个数和实参个数可以是不一样的
函数的形参可以通过function_name.length可以获得
函数的实际参数 内部就是一个数组去接收函数的实际参数arguments对象 可以访问函数的实际参数
arguments.length 返回函数的实际参数,arguments[0] arguments[1] 只能在函数的内部访问和使用
if (fn_name.length == arguments.length) {
alert("实参和形参的格式是一致")
}
arguments对象 用的最多的还是递归操作
arguments.callee其实是指向函数的指针arguments.callee();执行当前函数。
this对象
this对象是在运行时基于函数的执行环境绑定的。this对象总是指向调用者
call apply
每一个函数都包含两个非继承函数的方法,
call 将一个函数绑定到另外一个函数中,参数列表
apply 将一个函数绑定到另外一个函数中,参数数组
call apply 可以扩充函数生存的作用域 绑定作用域实际的对象中
window.color = "red";
window.obj = {color:"yellow"};
function showColor(){
alert(this.color);
}
showColor.call(window);//打印red
showColor.call(this);//打印red
showColor.call(window.obj);//打印yellow
//自定义对象
function Obj(x, y) {
this.x = x;
this.y = y;
return x*y;
}
function test(a, b) {
return a + b;
}
var o = new Obj(10, 20);
o.method = test;
o.method(o.x, o.y);
test.call(o, o.x, o.y);
执行环境和作用域链-->执行环境就是代码执行中所处的位置,与变量的访问权限有关,作用域链在于嵌套变量的使用范围的保存
垃圾收集、块级作用域
垃圾收集方法 一 标记法 二 引用计数法(不常用)
javascript中并没有块级作用域的概念,在使用if for 等时应该格外小心
function test() {
for (var i = 0; i < 5; i++) {
alert(i);
}
alert(i);//此处i = 6 这表明javascript没有块级作用域
}
//js 中() 表示执行
function test() {
(function() {
for (var i = 0; i < 5; i++) {
alert(i);
}
})();//这样就实现了块级作用域的概念 这种方式其实()实现了返回一个函数直接量,然后在调用函数,还存在一个方式(funciton(){}());这种方式强制匿名函数运行
alert(i);//此处i就是underfined
}
闭包
js中闭包有两种形式 一种函数闭包 一种是对象闭包 --> 使用with实现
闭包和作用域链之间的关系
闭包访问外层作用域的变量
闭包的作用:就是在另外一个函数中可以访问函数内部的变量,将函数内部的变量长期保存在内存中,而不会被垃圾回收。
var name = "zhaojunyang";
var obj = {
name : "zhaojunyang_2",
getName : function() {
return function() {
return this.name;
}
}
}
obj.getName()();//此处打印的是zhaojunyang而不是zhaojunyang_2
闭包的概念:一个函数 可以访问另外一个函数作用域中的变量
封闭性:private 起到一个保护变量的作用,函数内部的函数能够访问当前函数中的临时变量
var name = "zhaojunyang";
var obj = {
name : "zhaojunyang_2",
getName : function() {
var o = this; //此处一直被引用,无法进行垃圾回收,直到当前返回函数不被使用
return function() {
return o.name;
}
}
}
第五讲 面向对象js
js中类的概念
一 工厂模式 这不是最标准的方式
function createPerson(name, sex, age) {
var obj = new Object();
obj.name = name;
obj.sex = sex;
obj.age = age;
return obj;
}
var person = createPerson('zhaojunyang', '男', '19');
二 构造函数式
function Person(name, sex, age) {
this.name = name;
this.age = age;
this.sex = sex;
this.sayName = function() {
return this.name;
}
}
//为那个对象调用构造函数,传递一个指针给新创建的对象作为 this 指针。 然后构造函数根据传递给它的参数初始化该对象
var person = new Person('zhaojunyanng', '男', '20');
alert(person instanceof Person);
alert(person instanceof Object);
function Student(name, sex, age, grade) {
Person.call(this, name, age, grade);
this.grade = grade;
this.getGrade = funciton() {
return this.grade;
}
}
原型
创建每一个函数都有一个prototype属性,这个属性其实就是一个指针,而这个指针总指向一个对象,这个对象的用途就是将特定的属性和方法包含在内,起到一个所有实例所共享的作用
hasOwnProperty();判断是否是实例属性
alert(attr in Object)这个返回boolean值; 判断是否是实例中的属性(包括原型和实例)
constructor属性不能被遍历
对象及成员的检查 可以使用for in 先遍历实例中的属性,然后遍历原型中的属性,如果实例中的属性和原型的中的属性一致,则实例中的属性具有优先权
对象是不是一个类的实例 obj instanceof class
默认对象的指定 with(obj) { value *= 2;}
任何一个实例都是在原型的基础上进行复制的
//代码的严谨性
var arr = [1, 2, 3, [4, 5, [6, 7], 8], 9];
Array.prototype.each = function(fn) {
try {
this.i || (this.i = 0);//实现代码之间的解耦合
if (this.length > 0 && arguments.length > 0 && fn.constructor == Function) {
while(this.i < this.length) {
var e = this[this.i];
if (e && e.constructor == Array) {
e.each(fn);
} else {
fn.call(e, e);//避免内存的占用
}
this.i++;
}
this.i = null;//垃圾回收机制回收
//delete this.i;//直接删除属性
}
} catch(ex) {
//do something
}
return this;
}
arr.each(function(item) {
alert(item);
});
删除变量的原则
一 使用var申明的变量
二 直接继承自原型的成员
delete 在删除一个不能删除的成员时,才会返回false,当删除一个不存在的成员或者继承自父代类/原型的成员都应当返回true
简单原型
原型对象默认的构造器就是构造函数
原型中构造器发生改变之后,再定义变量,这样的变量指向的原型是修改后的原型。
function Person() {}
Person.prototype = {
name : "z3",
age: 20,
job: "程序员",
say: function() {
alert(this.job);
}
}
var p = new Person(); //此时的原型是object;
function Person() {}
Person.prototype = {
constructor:Person,
name : "z3",
age: 20,
job: "程序员",
say: function() {
alert(this.job);
}
}
var p = new Person(); //此时的原型是Person;
function Person() {}
var p = new Person(); //此时的原型是Person,即使下面定义了constructor,也切断了原来构造器之间的联系
Person.prototype = {
constructor:Person,
name : "z3",
age: 20,
job: "程序员",
say: function() {
alert(this.job);
}
}
p.say();
原型对象存在的问题:原型对象里的属性和方法 被所有构造器实例化对象所共享
组合使用原型和构造函数式
function Person(name, age, job, friends) {
this.name = name;
this.age = age;
this.job = job;
this.firends = friends;
}
Person.prototype = {
constructor:Person,
say: function() {
alert(this.job);
}
}
动态原型模式 这种方式将代码组合到一起,更加直观
function Person(name, age, job, friends) {
this.name = name;
this.age = age;
this.job = job;
this.firends = friends;
//动态原型模式
if (typeof this.say != "function") {
Person.prototype.say = function() {
alert(this.job);
}
}
};
稳妥构造函数式 委托对象在非常安全的环境中 1、没有公共属性 2、 不能使用this对象
function Person(name, age) {
var name = name;
var age = age;
this.getName = function() {//这是一种闭包的方式
return name;
}
return this;
}
var p = new Person("zhaojunyang", "20");
js中实现继承
原型链(一般不这样使用)--> 既继承了父类的模板,也继承了父类的原型对象
function Animal() {};
function Dog() {};
Animal.prototype.name = "tigger";
Dog.prototype = new Animal();//原型对象的构造器指向了父类的构造器,实现了继承
var d = new Dog();
alert(Dog.prototype.name);
原型继承的实现方式,
类继承--> 只继承了模板,并没有继承父类的原型对象
function Animal(name) {
this.name = name;
}
function Dog(name, age) {
Animal.call(this, name);
this.age = age;
}
混合继承
function Animal(name) {
var name = name;
this.getName = function() {
return name;
}
}
Animal.prototype.age = 20;
function Dog(name) {
Animal.call(this, name);
}
Dog.prototype = new Animal();
模拟公有私有类型的构造器
function MyObject() {//这是一种类的封装实现
//这是私有类型
var data = 100;
//这是一种私有的类型
function _run(v) {
alert(v);
}
//这是一种public类型
this.value = "this data is: ";
this.run = function() {
_run(this.value + data);
}
}
var o = new MyObject();
o.run();
模拟extjs底层实现继承
extend = function(sub, sup) {//此处只继承一个父类的原型,而不继承父类的模板
var F = new Function();
F.prototype = sup.prototype;
sub.prototype = new F();
sub.prototype.constructor = sub;//还原子类的构造器
sub.supClass = sup.prototype;//自定义一个子类的静态属性
}
第六讲 设计模式
接口
注解描述方式
/**
* interface Composite() {
* function add(obj);
* function remove(obj);
* }
*/
//CompositeImpl implements Composte
var CompositeImpl = function() {
if (typeof this.add != "function") {
arguments.callee.prototype.add = function() {
alert("add");
}
}
if (typeof this.remove != "function") {
arguments.callee.prototype.add = function() {
alert("add");
}
}
}
var c = new CompositeImpl();
c.add();
属性检测方式
/**
* interface Composite() {
* function add(obj);
* function remove(obj);
* }
*/
//CompositeImpl implements Composte
var CompositeImpl = function() {
this.implementNames = ["Composite"];
if (typeof this.add != "function") {
arguments.callee.prototype.add = function() {
alert("add");
}
}
if (typeof this.remove != "function") {
arguments.callee.prototype.add = function() {
alert("add");
}
}
}
var checkCompositeImpl = function(instance) {
if (isImplement(instance, "Composite")) {
throw new Error("Object is not implements the interface!");
}
}
function isImplement(Object) {
for (var i = 1; i < arguments.length; i++) {
var interfaceName = arguments[i];
var implementFound = false;
for (var j = 0; j < Object.implementNames.length; j++) {
if (interfaceName == Object.implementNames[j]) {
implementFound = true;
break;
}
}
if (!implementFound) {
return false;
}
}
return true;
}
var c = new CompositeImpl();
c.add();
鸭式辩型方式
//定义一个接口 接收两个参数,接口名,接口方法
function Interface(name, methods) {
if (arguments.length < 2) {
throw new Error(" the interface constructor arguments < 2 ");
}
this.name = name;
this.methods = [];
for (var i = 0, len = methods.length; i < len; i++) {
if (typeof methods[i] !== "string") {
throw new Error(" the method type is not string ");
}
this.methods.push(methods[i]);
}
}
//定义两个接口
var Composite = new Interface("Composite", ["add", "remove"]);
var Item = new Interface("Item", ["select", "update"]);
//定义接口实现类
function CompositeImpl() {
if(typeof this.add !== "function") {
arguments.callee.prototype.add = function() {
alert("add");
}
}
if(typeof this.remove !== "function") {
arguments.callee.prototype.remove = function() {
alert("remove");
}
}
if(typeof this.update !== "function") {
arguments.callee.prototype.update = function() {
alert("update");
}
}
if(typeof this.select !== "function") {
arguments.callee.prototype.select = function() {
alert("select");
}
}
}
Interface.ensureImplements = function(object) {
if (arguments.length < 2) {
throw new Error("the interface implements arguments should >= 2 ");
}
for (var i = 1; i < arguments.length; i++) {
var instanceInterface = arguments[i];
if (instanceInterface.constructor !== Interface) {
throw new Error("the arugments constructor not be Interface Class ");
}
for (var j = 0; j < instanceInterface.methods.length; j++) {
var methodName = instanceInterface.methods[j];
if (!object[methodName] || typeof object[methodName] !== "function") {
throw new Error(" the implements class not exist method: " + methodName );
}
}
}
}
var c = new CompositeImpl();
Interface.ensureImplements(c, Composite, Item);
c.add();
单体模式(单例模式)
简单单体 -->还有一个作用就是 划分命名空间
var Ext = {};
var Ext.Array = {};
var Ext.String = {};
var Single = {
};
闭包单体 -->这种方法使得代码更加严谨 闭包的主要目的就是保护数据
var Singleton = (function(){
//此处可以添加私有成员量
var attr1 = true;
var attr2 = 20;
var fn1 = function() {
alert("fn1");
}
//返回一个单体对象
return {
property1: attr1,
property2: attr2,
function1: function() {
return fn1();
}
};
}());
惰性单体
var Singleton = (function(){
//此处添加私有成员量,控制返回的单体变量的类型
var base;
var core;
function init() {
var attr1 = true;
var attr2 = 20;
var fn1 = function() {
alert("fn1");
}
return {
property1: attr1,
property2: attr2,
function1: function() {
return fn1();
}
}
}
function init_core() {
var attr1 = true;
var attr2 = 20;
var fn1 = function() {
alert("fn1");
}
return {
property3: attr1,
property4: attr2,
function2: function() {
return fn1();
}
}
}
//返回一个单体对象
return {
getInstance: function(object) {
if (object === "base") {
if (!base) {
base = init();
}
return base;
}
if (object === "core") {
if (!core) {
core = init_core();
}
return core;
}
}
};
}());
Singleton.getInstance("core").function2();
分支单体 --> 判断程序的分支-- 浏览器的差异
函数的链式调用-- jQuery
function Dog() {
this.run = function() {
alert("run");
return this;
}
this.eat = function() {
alert("eat");
return this;
}
}
var d = new Dog();
d.run().eat();
模拟jQuery底层链式调用
//特点1 程序启动的时候 里面的代码直接执行了
//特点2 内部的成员变量 外部无法去访问 (除了不加var修饰的变量)
(function(window , undefined) {
// $ 最常用的对象 返回给外界 大型程序开发 一般使用'_'作为私用的对象(规范)
function _$(arguments) {
// 正则表达式匹配id选择器
var idselector = /#\w+/ ;
this.dom ; // 此属性 接受所得到的元素
// 如果匹配成功 则接受dom元素 arguments[0] = '#inp'
if(idselector.test(arguments[0])){
this.dom = document.getElementById(arguments[0].substring(1));
} else {
throw new Error(' arguments is error !');
}
};
// 在_$的原型对象上 加一些公共的方法
_$.prototype = {
constructor : _$ ,
addEvent:function(type,fn){
// 给你的得到的元素 注册事件
if(window.addEventListener){// FF
this.dom.addEventListener(type , fn);
} else if (window.attachEvent){// IE
this.dom.attachEvent('on'+type , fn);
}
return this ;
},
setStyle:function(prop , val){
this.dom.style[prop] = val ;
return this ;
}
};
window.$ = _$ ; // window 上先注册一个全局变量 与外界产生关系
// 写一个准备的方法
_$.onReady = function(fn) {
window.$ = function() { // 1 实例化出来_$对象 真正的注册到window上
return new _$(arguments);
};
fn(); // 2 执行传入进来的代码
};
})(window); // 程序的入口 window传入作用域中
$.onReady(function(){
var inp = $('#inp');
//alert(inp.dom.nodeName);
//alert($('#inp'));
inp.addEvent('click',function(){
alert('我被点击了!');
}).setStyle('backgroundColor' , 'yellow');
});
//设计模式
function Dog() {
Dog.prototype.run = function() {
alert("dog is run...");
}
}
function Cat() {
Cat.prototype.run = function() {
alert("cat is run...");
}
}
//简单工厂方法
function AnimalFactory() {
if (typeof AnimalFactory.prototype.create != "function") {
AnimalFactory.prototype.create = function(type) {
var animal;
switch(type) {
case "dog" : animal = new Dog(); break;
case "cat" : animal = new Cat(); break;
default: break;
}
return animal;
}
}
}
var af = new AnimalFactory();
var animal = af.create("dog");
animal.run();
posted on 2016-07-26 07:57 zhaojunyang 阅读(114) 评论(0) 收藏 举报
浙公网安备 33010602011771号