JavaScript基础
延迟加载
<script>有一个布尔型的属性defer,设置该属性,可以使javascript文件在页面解析完成后再加载。
<script type="text/javascript" defer >
异步加载
默认情况下,页面是同步加载javascrip文件的,如果JavaScript,文件过大,会影响HTML代码继续。设置异步加载,在加载javaScript文件时,不影响HTML的加载。
<script type="text/javascript" async >
变量作用域
-
全局变量:在整个页面中都可以看见,可以自由访问
-
局部变量:仅仅在申明的函数内部可以看见,函数外不可以访问
-
作用域提升:在局部变量中,不声明变量,变量将会被提升一个作用域
function f() { b=100; // b 将被提升为全局变量 function f1() { // a=10; 变量a 不会被提升为全局变量 } }
数据类型
javaScript的6种数据类型
-
null 空值 表示非对象
-
undefined 未定义值 表示未初始化
-
number 数字
-
string 字符串
-
boolean 布尔值
-
objiect 对象
typeof
-
检查6种基本数据类型
-
typeof将 对象 数组 函数 null 均判断为objiect对象
-
null undefined number string boolean 均返回对应字符串
constructor
constructor是Object的原型属性,他能返回当前对象的构造器,即构造函数。
var o = {}; var a = []; if (o.constructor == Object) document.write("o S是对象"); if (a.constructor == Array) document.write("a是数字") ;
undefined 和null 没有constructor属性,不能读取,会抛出异常
对象操作运算符号
in
in 运算符号可检查出 左边的操作数是否为右边操作数的成员属性,就有继承关系的属性,也会判断为true。比如Objiect的valueOf和constructor等属性
var o ={ a: 10 }; console.log("a" in o) ; //true console.log("b" in o) ; //false
instanceof
检测当前对象是否为构造器的实例
var a = new Array(); console.log(a instanceof Array) ; //true console.log(a instanceof Object); //true console.log(a instanceof Function); //flash
delete
删除指定对象的指定属性,或者数组的元素,成功返回ture
var a ={ x : 1, y : 2 }; console.log(a.x) //输出 1 console.log(delete a.x) //ture
函数
使用call和apply
call和apply是Function的原型方法,他们将指定方法绑定到指定对象上执行,执行是方法的This指向指定的对象。
//参数为多个 function.call(Object, args..) //参数为数组 function.apply(Object,[args])
arguments
arguments是函数的内部伪类数组,只在函数类可见,是当前函数执行时的实参数组
callee
是arguments对象的属性,她引用当前arguments对象所在的函数,即函数本省。可以通过他获取函数的形参。
this
函数内的关键字,this是一个指针,指向动态引用的运行环境,也就是调用函数的对象。一个全局变量的方法执行时,this指向windows对象。
闭包
利用作用域连,使函数外部可以访问到函数内部的数据。
当函数被调用时,会产生一个上下文活动对象,他是函数的顶级作用域。函数内的变量,私有变量,参数,私有函数,都作为上下文对象的属性存在。函数巡行结束后,上下文对象随着被立即释放。但是当有私有的参数,变量,函数被外部引用时,上线文环境不会立即清理,知道所有的外部引用被注销。
//模拟存储 var get; var add; var inc; function test() { var indexcache = 0; get=function () { return indexcache; }; add=function (x) { indexcache+=x; return indexcache; }; inc=function (x) { indexcache -=x; return indexcache; }; } test(); console.log(add(10)); //10 console.log(inc(10)); //0 console.log(get()) ; //0 //立即释放掉 get=null; add=null; inc=null;
闭包的缺陷:
-
闭包的数据是动态的,需要注意数据的变换
-
闭包不会理解被释放,js脚本中如果大量使用,会比较占用计算机的内存
函数合成
函数合成,为了解决函数多层调用,如:a(b(c(x))),不优雅的文件。
简单实现:
function compode(a, b, c){ //先判读,参数匹配 if (arguments.length!=arguments.callee.length){ throw new Error("参数个数不匹配") } //先判断所有参数优势函数 for (var s in arguments){ if (s instanceof Function){ throw new Error("所有的参数,必须是函数") } } //返回合成函数 return function (x) { return a(b(c(x))) } } function a(x) { return x + 5; } function b(x) { return x*10; } function c(x) { return x/2; } console.log(compode(a,b,c)(10));
java对象
构造对象
使用new 运行符号调用构造函数
var objiectName = new functionName(args);
-
objiectName :返回的实例对象名
-
functionName:函数函数,和普通函数基本一致,但是不需要返回值。返回的实例对象,可以在构造函数中,使用this预先进行访问配置
-
args: 参数 (可以使用 arguments 对象,对函数进行重构)
-
构造函数的返回值,如果不是对象,将失效,如果是对象,则返回对象
function CreateUser(username,password,age) { console.log(username.constructor) ; if (typeof username!="string"){ throw new Error("username必须是String类型") } if (typeof password!="string"){ throw new Error("username必须是String类型") } if (typeof age !="number"){ throw new Error("Age必须是Number") } this.username =username; this.password =password; this.age =age; this.toString=function(){ document.write(this.username+this.password+this.age); } }
直接对象
直接对象可以快速定义对象,高效,快捷,简单。、
var objectName ={ nanmA : 100 , //数字 nameB : "我是字符串", //STring nameC : { NameE : "我也可以是对象" }, nameD : function () { console.log("我是函数") } }
Objiect.create
Object.create(Prototype, descriptors)
Prototype: 必须参数,指定的原型对象,可以实现原型对象绑定。(也可以直接给对象的原型对象属性赋值)
descriptors: 可选参数,包含一个或者多个属性,描述JS对象。属性描述包含数据特性和访问特性,特性参数如下:
-
vakue : 指定的属性值
-
writable:默认false,设置的属性值,是否可写
-
enumerable: 默认为false,设置的属性值,是否可以被枚举,主要是使用(for in)变量属性
-
configurable: 默认false ,是否可以修改属性特性和删除属性特性
function CreateUser(username,password,age) { console.log(username.constructor) ; if (typeof username!="string"){ throw new Error("username必须是String类型") } if (typeof password!="string"){ throw new Error("username必须是String类型") } if (typeof age !="number"){ throw new Error("Age必须是Number") } this.username =username; this.password =password; this.age =age; this.toString=function(){ document.write(this.username+this.password+this.age); } } var user = new CreateUser("小明","dsdsds",25); var newUser=Object.create(user,{ adder:{ value:"广州", enumerable:true }, phoneNumber:{ value:"1236558955", enumerable:true }, toString:{ value:function () { document.write(this.username+this.password+this.age+this.adder+this.phoneNumbe+"<br/>"); }, enumerable:false } }); newUser.toString();
注解:原型对象的属性可以被对象重写,重写后只能在对象内部才能调用被重写过的方式。对象外只能调用重写后的方法
//获取到对象的原型对象 Object.getPrototypeOf(newUser) //获取到对象的属性描述对象 console.log(Object.getOwnPropertyDescriptor(newUser,"adder"));
操作对象
引用对象
对象的引用是引址引用,赋值操作,其实就是把对象的指针指导同一地址
var Obj = { x:true, y:false } var obj1 = ob console.log(obj1===obj) //true
复制对象
先新建对象,在逐一把属性赋值
var Obj = { x:true, y:false } var obj1; for (var i in obj){ obj1[i]=obj[i]; } console.log(obj1===obj) //false
克隆对象
利用构造函数的原型对象,在创建对象是,完成新对象的原型对象赋值
var clone = function (obj) { //构建空对象函数 function Temp() {}; //赋值原型对象 Temp.prototype = obj; return new Temp(); }
销毁对象
//新建对象 var obj ={}; // 销毁对象 obj=null;
操作对象属性
定义属性
添加属性,以及给对象添加新的属性
Object.defineProperties(object,propertyname,descriptor);
-
object :需要操作的对象
-
propertyname : 需要添加的属性名
-
descriptor : 描述属性的特性,格式如下
-
{
value : 1 , //属性值
writable:false, //默认 false,是否可写
enumrable:false,//默认falsh ,是否可以枚举
configurable:false //是否可以修改属性特性
}
Object.defineProperties(Object,descriptor);
descriptor:基本同上,只是构造函数的异构
先可以通过 " ." 语法给对象添加属性,所有特性值,默认为ture
var x ={}; x.name = "神奇的珂珂"; //添加属性 x.name = "张珂"; //修改属性 console.log(x.name); //获取属性 张珂
读写属性
Object.getOwnPropertyNames(x); //获取属性的私有属性的名称 Object.keys(Object); //获取可以枚举的属性名 Object.getOwnPropertyDescriptor(x,"name") //获取属性的特性
原型方法
Object的原型方法定义在Object.prototype对象上,也叫实例方法
toString()
返回一个能表示对象的的字符串,一般是类型名,也可以重新toString方法
valueOf()
返回对象的值
hasOwnProperty( )
检查私有属性
构造函数和原型
构造函数
定义构造函数
function 构造函数名(配置参数) { this.属性名1 = 属性值1, this.属性名2 = 属性值2, ... this.方法名 =function () { //代码 } ... }
-
构造函数首字符需要大写,以区分方法
-
this,指向将要生成的实例对象
-
构造函数需要使用 this调用
-
构造函数不需要返回值,如果有返回值,返回值不是对象会被忽略,是对象则返回对
-
构造函数可以接受参数,可以使用arguments实现函数的异构
原型
JS中每个函数都都原型对象,函数实例化后,实例对象可以通过prototype访问原型对象
访问原型对象
-
obj._ proto _
-
obj.constructor,prototype
-
Object.getPrototypeOf( obj)
设置原型对象
var ss ={}; ss.__proto__={ name:"ss" }; console.log(ss.name); Object.setPrototypeOf(ss,{ name:"ddd" }); console.log(ss.name) ; ss =Object.create({ name:"dsdsdsd" },ss) console.log(ss.name);
检查原型对象
isPrototypeOf()方法可以判断该对象是否是参数的原型对象
function F() { } var obj = new F(); var pro = Object.getPrototypeOf(obj); console.log(pro.isPrototypeOf(obj)); //ture var sss ={ name: "sdsdsds" }; obj.__proto__ =sss; console.log(sss.isPrototypeOf(obj)); //ture
原型连
在js中,实例对象在读取属性时,会先检查私有属性是否有指定属性,如果不存在则会去prototype对象中寻找,如果有返回属性值。
如果原型对e象还存在引用关系,则会根据引用关系,依次向上寻找,依次类推,到最后一个原型对象。
function A(x) { this.x1=x; this.get1=function () { return this.x1; } } function B(x) { this.x2 =x; this.get2=function () { return this.x2+this.x2; } } B.prototype = new A(1); function C(x) { this.x3 =x; this.get3=function () { return this.x3*this.x3; } } C.prototype =new B(2); console.log( new C(3).get3()); console.log( new C(3).get2()); console.log( new C(3).get1());
扩展原型方法
Function.prototype.hello=function () { console.log("hello"); } Number.hello(); //输出 hello //原因 console.log(Number instanceof Function); console.log(Number.constructor);
Function,她本身也是一个够着函数。Number是一个数字的构造方法,在js方法也是对象。