1基本(值)类型 / 对象(引用)类型 / 判断
1.1基本数据类型
undefined:表示缺少值,即此处应该有值,但没有定义
null:表示没有对象,即此处不应该有值;
初始赋值为null表示将要赋值为对象(因为typeof为object);结束前赋值为null表示垃圾对象被回收(全局变量不会释放)
boolean
number:表示整数和浮点数
string
1.2对象(引用)类型
object
Array
function
基本类型传递的是值,引用类型传递的是地址
1.3判断
1.3.1 typeof:判断数据类型,返回值有number,boolean,string,function,object,undefined,在判断null、array、object以及函数实例(new + 函数)时,得到的都是object
可以判断undefined,typeof a === “undefined”,因为返回的是数据类型的字符串表达
1.3.2 instanceof:判断该对象是谁的实例,必须为引用类型
//class类的实例对象
Integer integer = new Integer(1);
System.out.println(integer instanceof Integer);//true
//为class接口的实现类
ArrayList arrayList = new ArrayList();
System.out.println(arrayList instanceof List);//true
List list = new ArrayList();
System.out.println(list instanceof ArrayList);//true
//为class类的直接或间接子类
Person p2 = new Man();
Man m1 = new Man();
System.out.println(p2 instanceof Man);//true
System.out.println(m1 instanceof Man);//true
1.3.3 ===
判断undefined,a === undefined
2对象 / 数组 / 引用变量 / 函数
2.1对象和数组
//下例 一个数组中有多个对象,每个对象中又有数组
//对象 instanceof object为true,对象 instanceof Array为false
//数组用“[]”创建,对象用“{}”创建
var ps = [
{
teacherName:'1',
students:['111','222']
},
{
teacherName:'2',
students:['333','444']
}
];
2.2引用变量
2.2.1 var a = xxx,a内存保存的是:
xxx是基本数据,保存的是这个数据;
xxx是对象,保存的是对象的地址值
2.2.2两个引用变量指向同一个对象,通过一个变量修改对象内部数据,另一个变量看到的是修改之后的数据
var obj1 = {name:"Tom};
var obj2 = obj1;
obj2.age = 12;
console.log(obj1.age); //为12
2.2.3两个引用变量指向同一个对象,让其中一个引用变量指向另一个对象,另一引用变量依然指向前一个对象
var a = {name:"Tom};
var b = a;
a = {name:"Jack"}; //注意此处改变指向对象
console.log(b.name); //为Tom
function f1(obj){
obj = {name:"Rose"}
}
f1(a);
console.log(a.name); //为Jack,a赋值给obj,同一个地址,obj又指向其它对象,改变地址
2.3函数
2.3.1function b(){} 为函数声明
//function a(){}属于封装函数,这个可以写在调用之后
function a(){}
a()
//或者都可以,因为存在函数提升规则
a()
function a(){}
2.3.2var a = function(){} 为函数表达式
//必须写在调用a之前
var a = function(){}
a();
2.3.3匿名函数
(function(){//匿名函数自调用
console.log("...");
})()//将函数用括号包裹,后面加括号执行
2.3.4
var obj = {};
function test(color){}
test.call(obj, "black"); //让函数成为对象的方法,后面传参
3 this / prototype / 原型链 / js继承 / 变量提升 / 上下文
3.1 this指向
1)test():window
2)p.test():p
3)new test():新创建的对象
4)p.call(obj):obj
3.2 prototype
1)函数的prototype(属性值)
每个函数都有一个prototype属性,它默认指向一个object空对象(即:原型对象)
原型对象中有一个属性constructor,它指向函数对象
2)给原型对象添加属性(一般是方法)
作用:函数的所有实例对象自动拥有原型中的属性(方法)
function Fun(){} // 内部语句:this.prototype = {}
//给原型对象添加属性(一般是方法),给实例对象使用
Fun.prototype.test = function(){}
Fun.prototype.constructor // 这是构造方法,为Fun
//实例访问
var fun = new Fun();
fun.test();
3)对象的隐式原型的值为其对应构造函数的显示原型的值
//前显示,后隐式
//前者函数对象创建(即定义)时有prototype值,后者在实例对象(即new)时创建__proto__
//内部语句 this.__proto__ = Fun.prototype;
console.log(Fun.prototype === fun.__proto__); //为true
4)传值
function Person(name, age){
this.name = name;
this.age = age;//this设置,方法中可获取传入的值
}
Person.prototype.setName = function(name){
this.name = name
}
var person = new Person("Jack",12)
person.setName("Rose");
3.3原型链
原型链:arr —> Array.prototype —> Object.prototype —> null
层层向上查找,最后还没有就返回undefined
arr.__proto__ === Array.prototype //true
Array.prototype.__proto__ === Object.prototype //true
arr.__proto__.__proto__ === Object.prototype //true
// 原型链的终点
Object.prototype.__proto__ === null //true
3.4 js的继承
3.4.1属性继承
属性的继承是通过在一个类内执行另外一个类的构造函数
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.getName = function(){
console.log(this.name);
}
function Teacher(name, age, subject){
Person.call(this, name, age);
//call指定this为当前执行环境,这样就可以得到另外一个类的所有属性。
this.subject = subject;
}
3.4.2方法继承
把Person.prototype的备份赋值给Teacher.prototype
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;
3.5变量提升
先执行变量提升,再执行函数提升
3.5.1变量声明提升
通过var定义(声明)的变量,在定义语句之前就可以访问到
值:undefined
3.5.2函数声明提升
通过function声明的函数,在之前就可以直接调用
值:函数定义(对象)
例如:
fn3();
var fn3 = function(){//此时为函数表达式,为变量提升
console.log("fn3")'
}
3.6执行上下文
全局上下文
函数执行上下文:函数调用时产生(定义不是)
4return / break / continue / 作用域 / 闭包 / call
4.1return / break / continue
break:跳出所在的当前整个循环,一层循环
continue:跳出本次循环,从下一个迭代继续运行循环
return:从当前的方法中退出,返回到该调du用的方法的语句处,继续执行
4.2作用域
var fn = function(){
console.log(fn)
}
fn() //能输出
var obj = {
fn2: function(){
console.log(fn2) //报错,因为作用域在大括号内,没有找到就去全局作用域找,但是没有;也可理解为fn2为对象的属性,不是声明的变量
// 加this与不加this的区别!
console.log(this.fn2) // 可以输出
}
}
obj.fn2()
4.3闭包
闭包时嵌套的内部函数
产生闭包的条件:
1)函数嵌套
2)内部函数引用了外部函数的数据(变量/函数)
例1:
function fn1(){
var a = 1;
var b = "abc"
//若为var fn2 = function调用外部函数不会产生闭包,因为函数对象还没创建
function fn2(){//执行函数定义即fn1()就会产生闭包,不用调用内部函数
console.log(a) //闭包含a不含b,因为没调用b
}
}
fn1()
例2:
//将函数作为另一个函数的返回值
function fn1(){
var a = 2
function fn2(){
a++
console.log(a)
}
return fn2()
}
var f = fn1()
//fn1()的值赋值给f,fn1()的值是return的内部函数fn2,f为调用内部函数,内部函数闭包未销毁
f() //3
f() //4
f = null // 闭包死亡
例3:立即执行匿名函数
//第一对括号内,是一个匿名函数,第二个括号会立即调用这个匿名函数的返回值,也就是匿名函数中的内容被立即执行
//特点:独立了一个作用域(括号中内容执行完后会被立即回收),内部变量外部无法访问,而它又能通过this保留字,来访问外部变量
var i = 100;
(function(){
var j = 1;
this.plus_ij = function(){
j+=i;
alert(j);
}
})();
plus_ij();
例4:this和that
var name = "The Window"
var object = {
name:"My Object",
getNameFunc:function(){
return function(){
return this.name
}
}
}
alert(object.getNameFunc()());//立即执行函数,函数体内this为window
var name2 = "The Window"
var object2 = {
name2:"My Object",
getNameFunc:function(){
var that = this
return function(){
return that.name2 //该处that为object2
}
}
}
例5:父子类型
使用call为了能看到属性,继承父类为了使用方法
//父类型
function Supper(){ this.supProp = 'Supper property' }
Supper.prototype.showSupperProp = function(){ console.log(this.supProp) }
//子类型
function Sub(){ this.subProp = 'Sub property' }
//子类型的原型为父类型的一个实例对象
Sub.prototype = new Supper()
//让子类型的原型的constructor指向子类型
Sub.prototype.constructor = Sub
Sub.prototype.showSubProp = function(){ console.log(this.subProp) }
var sub = new Sub()
sub.showSupperProp() //可以使用父方法
4.4 call()
用法一:
obj1.(method).call(obj2,argument1,argument2)
如上,call的作用就是把obj1的方法放到obj2上使用,后面的argument1…这些做为参数传入
function add(x, y){ console.log(x+y) }
function minus(x, y){ console.log(x-y) }
add.call(minus, 1, 1)//2
用法二:
A.call( B,x,y ):就是把A的函数放到B中运行,x 和 y 是A方法的参数
用call来实现继承,用this可以继承myfunc1中的所有方法和属性
function myfunc1(){
this.name = 'Lee'
this.myTxt = function(txt){ console.log('i am', txt) }
}
function myfunc2(){ myfunc1.call(this) }
var myfunc3 = new myfunc2()
myfunc3.myTxt('Geing')
用法三:
让括号里的对象 来集成括号外的函数的属性
apply第二个参数必须传入的是一个数组,而call 第二个参数可以是任意类型
function changeStyle(attr, value){
this.style[attr] = value
}
var box = document.getElementById('box')
window.changeStyle.call(box,"height","200px")
window.changeStyle.apply(box,['height','200px'])//apply用法
5 Worker
Worker要在服务器下运行
5.1服务器http-server
1)安装http-server
cnpm install -g http-server
2)启动
http-server
5.2 postMessage 和 onmessage
//主线程
var number = input.value
//放入分线程,创建一个Worker对象
var worker = new Worker('worker.js')
//向分线程发送消息
worker.postMessage(number)
console.log("主线程向分线程发送数据:" + number)
//绑定接收消息的监听
worker.onmessage = function(event){
console.log("主线程接收分线程返回的数据:" + event.data)
alert(event.data)
}
woker.js
//分线程
function fc(n){
return n<=2?1:fc(n-1)+fc(n-2)
}
//分线程不能更新页面,因为分线程全局对象不是window
//不能调用alert / document 等
var onmessage = function(event){
var number = event.data
console.log("分线程接收到主线程发送的数据:"+number)
var result = fc(number)
postMessage(result)
console.log("分线程向主线程返回数据:"+result)
}
5.3其他
1)加载其他脚本:importScripts(‘script1.js’, ‘script2.js’);
2)使用完毕,关闭worker
// 主线程
worker.terminate();
// Worker 线程
self.close();