/**************************************************************/
<a href="#" onclick="history.back()">返回</a>
window.location.href=test01.html
window.open():
document.getElementById("wel").style.display = "none";
btn.onclick = function(event){
event = event||window.event;
alert(event.type);
alert(this.value);
}
//先加载页面后加载方法
window.onload = init;
<body onload = init()></body>
funcion init(){ }
/**************************************************************/
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
var x = function(){
alert("x");
//对于函数而言,直接写return就等于有返回值
return 100;
};
x();
function fn() {
}
//此时是将y这个变量指向函数fn,可以通过y()来调用函数
var y = fn;
fun();
//可以调用
y();
//将函数fn所执行的函数值传递给z变量,所以z为100
var z = fun();
alert(z);
alert(y);
function Person(name,age){
//定义Person的属性
this.name = name;
this.age = age;
//如果没有用this声明,这个变量就仅仅是一个局部变量,不是类的属性
var x = 10;//局部变量,不能调用
this.say = function(){
alert(this.name+this.age);
}
}
var p1 = new Person("zhangsan",12);
alert(p1.name + p1.age);
alert(p1 instanceof Person);
p1.say();
//可以通过对象的[]完成对属性的调用
alert(p2["name"] +p2["address"]);
//在js中对于对象而言,可以通过for in 来变量对象的属性
for(var a in p1){
//可以获取对象中所有显示声明的属性
alert(a+":" + p1[a]);
}
</script>
</head>
<body>
</body>
</html>
/*****************************************************************/
//工厂方法创建Person对象
function createPerson(name,age){
var o = new Object();
o.name = name;
o.age = age;
o.say =function(){
alert(this.name + "," + this.age);
}
return o;
}
var p1 = createPerson("Leon",22);
var p2 = createPerson("Ada",33);
p1.say();
p2.say();
//构造方法创建Person对象
function createPerson(name,age){
this.name = name;
this.age = age;
this.say =function(){
alert(this.name + "," + this.age);
}
}
var p1 = new Person("Leon",22);
var p2 = new Person("Ada",33);
p1.say();
p2.say();
//通过原型的方式构造
function Person() {
}
Person.prototype.name = "Leon";
Person.prototype.age = 23;
Person.prototype.say = function(){
alert(this.name+","+this.age);
}
var p1 = new Person("Leon",22);
var p2 = new Person("Ada",33);
p1.say();
p2.say();
alert(Person.prototype.isPrototypeOf(p1));
alert(p1.hasOwnProperty("name");
/*****************************************************************/
function Person() {
}
Person.prototype = {
constructor:Person,//手动指定原型的constructor
name:"Leon",
age:123,
say: function () {
alert(this.name+","+this.age);
}
}
/*****************************************************************/
44---
/**
*基于原型的创建虽然可以有效的完成封装,但是依然有一些问题
*1、无法通过构造函数设置属性值
* 2、当属性中有引用类型变量值,可能存在变量值重复
* */
function Person() {
}
Person.prototype = {
constructor:Person,
name:"Leon",
age:30,
friends:["Ada","Chris"],
say: function () {
alert(this.name+"["+this.friends+"]");
}
}
var p1 = new Person();
p1.name = "John";
p1.say();//john[ada,chris]
//会在原型中找friends,所以Mike是在原型中添加的
p1.friends.push("Mike");
var p2 = new Person();
p2.say();//leon ada chris Mike
//-----------------------------------------------------------------------------------------------
/**
*为了解决原型带来的问题,此处需要通过组合构造函数和原型来实现对象的创建
* 这种属性在构造函数中定义,将方法在原型中定义
* 这种有效集合了两种的优点,是目前最为常用的一种方式
* */
function Person(name,age,friends) {
//属性在构造函数中定义
this.name = name;
this.age = age;
this.friends = friends;
}
Person.prototype = {
constructor:Person,
//方法在原型中定义
say: function () {
alert(this.name+"["+this.friends+"]");
}
};
//此时所有的属性都是保存在自己的属性中
var p1 = new Person("Leon",23,["Ada","Chris"]);
p1.name = "John";
p1.say();//john[ada,chris]
//会在原型中找friends,所以Mike是在原型中添加的
p1.friends.push("Mike");
var p2 = new Person("Ada",33,["Leon"]);
p2.say();//leon ada chris Mike
//-----------------------------------------------------------------------------------------------
44--
/**
* 动态原型
*为了让定义的方式更符合java的需求,就把定义的原型代码放置到person这个构造函数中
* */
function Person(name,age,friends) {
//属性在构造函数中定义
this.name = name;
this.age = age;
this.friends = friends;
if(!Person.prototype.say){
alert("aaa");
Person.prototype.say = function(){
alert(this.name+"["+this.friends+"]");
}
}
}
/* Person.prototype = {
constructor:Person,
//方法在原型中定义
say: function () {
alert(this.name+"["+this.friends+"]");
}
};*/
//此时所有的属性都是保存在自己的属性中
var p1 = new Person("Leon",23,["Ada","Chris"]);
p1.name = "John";
p1.say();//john[ada,chris]
//会在原型中找friends,所以Mike是在原型中添加的
p1.friends.push("Mike");
var p2 = new Person("Ada",33,["Leon"]);
p2.say();//leon ada chris Mike
/*****************************************************************/
45--继承
/**
* js实现继承的第一种方式是基于原型的链的方式
* */
function Parent() {
this.pv = "parent";
}
Parent.prototype.pp ="ok";
Parent.prototype.showParentValue = function(){
alert(this.pv);
};
function Child(){
this.cv ="child";
}
/**
* 让Child的原型链指向Parent对象,也就等于完成了一次继承
* 注意内存模型
*/
Child.prototype = new Parent();
Child.prototype.showChildValue = function () {
alert(this.cv);
};
var c = new Child();
c.showParentValue();
c.showChildValue();
alert(c.pp);
//-----------------------------------------------------------------------------------------------
/**
* js实现继承的第一种方式是基于原型的链的方式
* */
function Parent() {
this.pv = "parent";
}
Parent.prototype.pp ="ok";
Parent.prototype.showParentValue = function(){
alert(this.pv);
};
function Child(){
this.cv ="child";
}
/**
* 如果赋值之后,才进行原型链的设定,这样赋值的原型对象
* 就会被重写掉,赋值的对象就不存在新的原型对象中
*/
Child.prototype.showChildValue = function () {
alert(this.cv);
};
/**
* 让Child的原型链指向Parent对象,也就等于完成了一次继承
* 注意内存模型
*/
Child.prototype = new Parent();
/**
*当执行了下面这句话之后,意味着Child的原型又重写了
* 这样就不存在任何的继承关系了
* 使用原型链注意的第一个问题
*/
Child.prototype = {
showChildValue:function(){
}
};
/**
* 此时完成了对父类对象的重写
*/
Child.prototype.showParentValue = function(){
alert("override parent");
};
var c = new Child();
c.showParentValue();
c.showChildValue();
alert(c.pp);
/**
* 在使用原型链进行继承后一定要注意的问题:
* 1、不能在设定了原型链之后,再重新为原型链赋值
* 2.一定在原型链赋值之后才能添加或者覆盖方法
*/
//-----------------------------------------------------------------------------------------------
/**
* js实现继承的第一种方式是基于原型的链的方式
* */
function Parent() {
this.pv = "parent";
this.color = ["red","yellow"]
}
Parent.prototype.pp ="ok";
Parent.prototype.showParentValue = function(){
alert(this.pv);
};
function Child(){
this.cv ="child";
}
/**
* 使用原型链继承,最大的缺点是,无法从子类中调用父类的构造函数
* 这样就没有办法吧子类中的属性赋值给父类
* 第二个缺点就是,如果父类中有引用类型,此时这个引用类会添加到
* 子类的 原型中,当第一个对象的修改了这个这个引用之后,其他对象
* 同时修改
* 所以一般不会单纯的使用原型链来继承
*/
Child.prototype = new Parent();
Child.prototype.showChildValue = function () {
alert(this.cv);
};
/**
* 此时完成了对父类对象的重写
*/
Child.prototype.showParentValue = function(){
alert("override parent");
};
var c1 = new Child();
//Child中原型中color被修改
c1.color.push("blue");
alert(c1.color);
var c2 = new Child();
alert(c2.color);
/*****************************************************************/
46--基于伪装的继承方式
function Parent() {
this.color = ["red","yellow"];
this.name = "leon";
}
function Child(){
//在Child中的this明显应该是指向Child的对象
//当调用Parent方法的时候,而且this又是指向了Child
//此时就等于在这里完成了this.color = ["red","yellow"];
//也就等于在Child中有了this.color属性,这样也就变相的完成了继承
Parent.call(this);
//这种调用方式,就仅仅完成了函数的调用,根本无法实现继承
// Parent();
}
var c1 = new Child();
c1.color.push("green");
alert(c1.color);
var c2 = new Child();
alert(c2.color);
//-----------------------------------------------------------------------------------------------
function Parent() {
this.color = ["red","yellow"];
this.name = "leon";
this.say = function(){
alert(this.name);
}
}
/**
* 由于使用伪造的方式,不会完成Child的原型指向parent
* 所以say方法不存在,解决方法是,将这个方法放置到
* Parent中使用this来创建,但是每个对象中又存在say
* 这样空间占用太大,所以也不会单独的使用伪造的方式实现继承
*/
/* Parent.prototype.say = function(){
};*/
function Child(){
/**
* 使用伪造的方式就可以把子类的构造函数参数传递到父类中
*/
this.age = age;
Parent.call(this,name);
}
var c1 = new Child("Leon",12);
var c2 = new Child("Ada",22);
c1.say();
c2.say();
/*****************************************************************/
47--基于组合的方式实现继承
/**
* 组合的方式是属性通过伪造方法实现,方法通过原型链的方法实现
*/
function Parent(name) {
this.color = ["red","yellow"];
this.name = name;
}
Parent.prototype.ps = function(){
alert(this.name+","+this.age+"["+this.color+"]");
};
function Child(name,age){
//已经完成了伪造
Parent.call(this,name);
this.age = age;
}
Child.prototype = new Parent();
Child.prototype.say = function(){
alert(this.name+","+this.age+"["+this.color+"]");
};
var c1 = new Child("Leon",12);
c1.color.push("blue");
var c2 = new Child("Ada",22);
c1.say();
c1.ps();
c2.say();
c2.ps();
/*****************************************************************/
48--函数调用的作用域链
<script type="text/javascript">
fn1();
//不会报错,对于通过function fn()这种写法来定义的函数,永远都会被最先初始化
function fn1(){
alert("fn1");
}
// fn2();
/**
* 使用如下方式定义函数,不会被先执行,如果在之前调用该函数就会报错
*
* 以下函数的定义方式是先在内存中创建了一块区域,之后通过一个fn2的变量
* 指向这块区域,这块区域的函数开始时没有名称的,这种函数就叫做匿名函数
*/
var fn2 = function(){
alert("fn2");
};
/**
* 在js中当进行函数的调用,会为每一个函数增加一个属性scope,通过这个属性
* 来指向一块内存。这块内存中包含的所有的上下文使用的变量,当在某个函数中调用了
* 新函数之后,新函数依然会有一个作用域来执行原有的函数的scope和自己新增的
* scope,这样就形成了一个链式结构。
* 这就是js的一个作用域链
*/
var color = "red";
var showColor = function(){
alert(this.color);
};
function changeColor(){
var anotherColor = "blue";
function swapColor(){
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
}
swapColor();
}
changeColor();
showColor();
</script>
/*****************************************************************/
48--闭包
<script type="text/javascript">
/**
* 通过以下操作带来的最大的好处是,compareObjectFunction的作用域变大了
* 当compareObjectFunction结束之后,prop这个变量依然存在
*/
function compareObjectFunction(prop){
//匿名函数
return function(obj1,obj2){
if(obj1[prop]>obj2[prop])return 1;
else if(obj1[prop]<obj2[prop])return -1;
else return 0;
}
}
var o1 = {name:"leon",age:23};
var o2 = {name:"Ada",age:28};
//此时就是基于name来进行比较
/**
* 在java或者C++中,以下代码执行完成之后,需要进行内存的释放
* 此时对于java和C++这些静态语言而言,prop会被释放
* 但是在js中, 这个作用域却被放大了
*/
var compare = compareObjectFunction("age");
//此时就比较了o1和o2
/**
* 在js中,prop在这里依然可以被访问,这种通过返回函数来扩大函数的作用域的方法
* 就是闭包
*/
var rel = compare(o1,o2);
alert(rel);
</script>
/*****************************************************************/
49--闭包--作用域链
<script type="text/javascript">
function fn1(){
//创建了一个数组
var fns = new Array();
//i这个变量是保存在fn1这个作用域中的
for(var i=0;i<10;i++){
//(2)num这个变量保存在fns这个tf这个作用域,每一个闭包的num都是不一样
//所以此时所消耗的内存特别大
var tf = function(num){
fns[num] = function(){
return num;
}
};
tf(i);
/*(1) //数组中括号的只是一组函数
fns[i] = function(){
return i;
}*/
}
return fns;
}
var fs = fn1();
for(var i=0;i<fs.length;i++){
//(1)此时通过闭包来调用所有函数,当输出i的时候会去上一级的作用域中查找
//这个时候i的值已经是10,所以连续输出了10个10
//(2)每一个fs都是在不同的作用域链中,num也是保存在不同的作用域中,输出0-9
document.write(fs[i]()+"<br/>");
}
</script>
//-----------------------------------------------------------------------------------------------
<script type="text/javascript">
var name = "window";
var person = {
name:"zhangsan",
age:23,
say:function(){
return function () {
return this.name;
}
}
};
/**
* 当完成person.say()之后,这个函数就调用结束了,在这个函数调用结束之前
* this是指向person,但是在调用匿名函数的时候,this就指向window了,所以
* 得到的结果是window
*/
alert( person.say()());
</script>
//-----------------------------------------------------------------------------------------------
<script type="text/javascript">
var name = "window";
var person = {
name:"zhangsan",
age:23,
say:function(){
//that指向perosn
var that = this;
return function () {
return that.name;
}
}
};
/**
* 此时that是指向person的,所以调用that.name就是person中
* name
*/
alert( person.say()());
</script>
/*****************************************************************/
50--块作用域
<script type="text/javascript">
for(var i=0;i<10;i++){
}
//在js中没有块作用域,不管使用循环还是判断之后,这个变量会一直存在
/**
* 所以当在全局使用某个变量进行循环或者判断之后,这个变量可能会影响
* 到函数中的变量,所以在特殊情况下不要使用全局变量,而且使用全局变量
* 在作用域链的嘴上层,访问时最慢的
*/
var i; //此时会认为是无效语句,除非使用var i=0;
alert(i);
</script>
/*匿名函数*/
<script type="text/javascript">
/**
* 在一个团队进行开发时,可能会涉及到定义同名的全局变量,所以在开发中
* 一定养成如下习惯,将全局变量的代码放到一个匿名函数,并且马上调用
* 匿名函数,这样也可以执行全局变量的代码,但是这些变量被控制在开发人员
* 想要控制的作用域中了
*/
(function(){
for(var i=0;i<10;i++){
}
})();
function fn(){
alert(i);
}
fn();
</script>
<script type="text/javascript">
function Person(name) {
/**
*此时就没有办法直接访问name这个属性,因为没有this.name
* 要访问name只能通过this.getName,this.setName
* 但是使用这种方式创建私有变量带来的问题是,每个对象都存储
* 了大量的函数,解决的办法是通过静态私有变量来解决
*/
this.setName = function(value){
name = value;
};
this.getName = function(){
return name;
};
}
var p = new Person("aa");
alert(p.getName());
p.setName("bb");
alert(p.getName());
</script>
<script type="text/javascript">
var Person;
(function(){
//name在函数结束之后就消失,外面无法引用
var name = "";
Person = function(value){
name = value;
};
Person.prototype.setName = function(value){
name = value;
};
Person.prototype.getName = function(){
return name;
};
})();
var p1 = new Person("aa");
p1.setName("bb");
alert(p1.getName());
</script>
/*****************************************************************/
51--原型扩展
<script type="text/javascript">
/**
* 以下为String扩展了trim的方法去除空格
*/
String.prototype.trim = function(){
//js的正则表达式和Java很类似,区别是js是用//
return this.replace(/(^\s+)|(\s+$)/g,"");
};
var str = " aaaa ";
alert("|" +str.trim() + "|");
</script>
/*****************************************************************/