作用域链变量搜索原则
- 1.在使用一个变量的时候,首先在当前作用域链中查找 , 如果没有就去上一级作用域链中查找,直到0级作用域链
闭包
闭: 封闭 关闭的意思
包: 包裹 包装的意思
-
闭包技术:
- 1.作用域: 内层作用域可以访问外层(内层作用域-->外层作用域),反过来不可以
- 2.但是有的时候我们确实需要访问内层作用域(外层作用域->内层作用域)
- 3.闭包技术就是一种可以间接访问封闭空间私有数据的方法
-
访问数据:
- 1.直接return
- 一次性获取数据
- 每次获取的不是同一份数据
function fun(){ var obj = { name: 'zs' } return obj; } var obj1 = fun(); var obj2 = fun(); console.log(obj1 == obj2); // false
- 2.使用闭包,对直接返回数据进行函数包装
function demo(){ var obj = { name:'zs' } return function (){ return obj; } } var fun = demo(); var obj1 = fun(); var obj2 = fun(); console.log(obj1 == obj2);// true
- 3.返回多个数据
第一种方法 function demo(){ var name = 'ss'; var des = 'des'; return function(){ return[name,des] } } var func = demo(); var name1 = func()[0]; var des1 = func()[1]; console.log(name1,des1); 第二种方法 function demo(){ var name = 'sa'; var des = 's'; return [ function (){ return name; },function (){ return des; } ] } var func = demo(); var name1 = fun[0](); var des1 = func[1](); console.log(name1,des1); 第三种方法 : 对象保存 function fun(){ var name = 'd'; var des = 'qq'; return { getName : function (){ return name; }, getDes : function (){ return des; } } } var obj = fun(); var name1 = obj.getName(); var des1 = obj.getDes(); console.log(name1,des1);
- 1.直接return
闭包获取和设置数据
- 规范写法
function fun(){ var name = 'zs'; var age = 20; return { getName : function (){ return name; }, setName : function (newName){ if(newName == undefined)return; name = newName; }, getAge : function (){ return age; }, setAge : function (newAge){ if(newAge == defined)return; age = newAge; } } } var obj = fun(); console.log(obj.getName()); obj.setName('ls'); console.log(obj.getName()); obj.setName(); console.log(obj.getName()); 注意点: 1.如果形参名与变量名相同,形参名无法传入,所以闭包要注意形参名不能与数据变量名同名 2.如果没有传参要做兼容处理
- 注意点:
- 1.如果形参名与变量名相同,形参名无法传入,所以闭包要注意形参名不能与数据变量名同名
- 2.如果没有传参要做兼容处理
闭包技术的作用
- 1.获取函数内部的数据只能通过指定的api(接口,方法)API application programming interface
- 2.在设置数据的时候更加安全
- 3.可以延长变量的生命周期
setTimeout 和闭包的执行
- setTimeout: 延迟执行函数(只会执行一次)
- setInterval: 每隔一定的时间执行一次(定时器)
- 进程: 正在运行的应用程序(工厂)
- 线程: 进程中用来执行任务的,同一时间只能执行一个任务(工人)
- JS是单线程
- 串行执行: 按照一定的顺序一个个的执行
- 并发执行: 多个任务同时执行
- 多线程: 有多条线程
- 多线程的原理: CPU同一时间只会调度一个线程,CPU是来回调度多个线程,造成多个任务同时执行的假象
for( var i = 0 ; i <10 ; i++){
setTimeout(function(){
console.log(i)//10次10
},0)
}
- ==JS的任务执行顺序==
- 1.渲染任务
- 2.代码的主要任务
- 3.事件性的任务(点击...)
- 解释了为什么都是10;
- 利用立即执行函数修正
第一种
for( var i = 0 ; i <10 ; i++){
(function (j){
setTimeout(function(){
console.log(i);
},0)
})(i);
}
第二种
for( var i = 0 ; i <10 ; i++){
setTimeout((function(j){
return function(){
console.log(j)
}
})(i),0)
}
div事件和闭包
- 立即执行函数修正JS任务执行顺序问题
- 方法两种:一;整体包装 二:函数包装(返回函数)
函数的特殊性
- 函数:
- 1.函数的也是一个对象
- 2.函数可以调用+ 作为参数+ 返回值 + 传参
- 3.函数可以创建作用域
- 函数name的特点:
- 只能获取,不能修改
函数的回调(作为参数传递)
- 把一个函数作为其他函数的参数,称为函数的回调
- 特殊情况
- 把对象的方法作为函数的参数 ---> this 丢失
var person ={ name : 'zs', showName: function(){ console.log(this.name); } } function func(callBack){ callBack();// '' window默认name为空字符串 } func(person.showName) 解决方法 call var person ={ name : 'zs', showName: function(){ console.log(this.name); } } function func(callBack,callBackObj){ callBack.call(callBackObj);// zs 让callBack的this绑定callBackObj 修正this指向 } func(person.showName,person)
函数作为返回值
- 函数可以作为其他函数的返回值
- 计数器
function func() { a =0; return function (){ a++; return a; } } var fun = func(); fun()
即时调用函数
- 语法:
- 1.(function(){})();
- 2.(function(){}())
- 3.+function (){
}() - 4.-function (){
}() - 5.!function (){
}()
即时对象初始化
var dataObj = {
name : 'zs',
des : 'des',
age: 20,
init: function (){
console.log('111')
}
}
// 即时对象初始化
({
name: 'zs',
des : 'des',
age: 20,
init: function (){
console.log('111')
}
}).init();
==惰性函数(初始化,常用)==
- 函数真正的内容需要执行一次才能确定,可以实现自我的更新
- 场合: 需要做一次初始化的操作
惰性函数
function func(){
console.log('func');
func = function (){
console.log('func-func');
}
}
func();//func
func();//func
-
注意点:
- 1.更新前,添加到函数上的属性,更新后就访问不到了(引用地址更改)
function foo(){ console.log('foo'); foo = function () { console.log('foo-foo'); } } foo.des = 'des'; console.log(foo.des);//des foo(); console.log(foo.des);//undefined
- 2.把惰性函数赋值给一个变量,以变量方式来调用,无法更新惰性函数(执行的都是外层函数)
function foo(){ console.log('foo'); foo = function (){ console.log('foo-foo'); } } var func = foo; func();//foo func();//foo
- 3.把惰性函数赋值给对象的方法,以对象的方法来调用,执行的外层函数(引用地址修改)
function foo(){ console.log('foo'); foo = function (){ console.log('foo-foo'); } } var obj = {name : 'zs'} obj.func = foo ; obj.func();//foo obj.func();//foo
面试题 01
以下创建对象的方式,错误的是:
var obj4;
obj4.name = "XMG";
obj4.getName = function () {
return this.name;
};
console.log(obj4); //false
面试题 02
请给出以下代码的打印结果
function test(){};
console.log(typeof test); // function
var test = '2018';
面试题 03
请给出以下代码的输出结果
var f = new Number(true);
if(f == true){
var a = 10;
}
function fn(){
var b = 20;
c = 30;
}
fn();
console.log(a); // 10
console.log(b); // 报错
console.log(c); // 30
面试题 04
请给出以下代码额输出结果
var name = 'world!';
(function(){
if(tyopeof name === 'undefined'){
var name = '张三';
console.log('hi'+name);
}eles{
console.log('hello'+name);
}
})();
// 结果: hi张三
面试题 05
请给出以下代码额输出结果
var a = {} , b = Object.prototype;
console.log([a.prototype ===
b,Object.getPrototypeOf(a)===b])
//A [fasle true]
//B [false false]
//C [true true]
//D [true false]
// 结果 A
面试题 06
请给出下面代码额输出结果
function f() {}
var a = f.prototype;
//Object.getPrototypeOf(对象) 用于获取实例对象的原型对象 这里把f 作为一个实例,他的原型对象是Function.prototype
var b = Object.getPrototypeOf(f);
console.log(a === b); // false | true
console.log((b == f)); // false | true
结果 false false
面试题 07
请给出以下代码的输出结果
function foo() { }
var oldName = foo.name;
foo.name = "bar";
console.log(oldName); // "foo"
console.log(foo.name); // "foo"
console.log(oldName === foo.name); // true
console.log([oldName, foo.name]); // ["foo","foo"]
面试题 08
请给出以下代码的输出结果
console.log(Array.isArray(Array.prototype))
// true
console.log(Object.prototype.toString.call(Array.prototype)); // [object Array]
面试题 08
请给出以下代码的输出结果
// [] [0] [1] 在条件判断为真,在== 值判断
if([0]){
console.log([0]== true);
}else {
console.log('NO');
}
结果 false
if([2]){
console.log([2]== true);
}else {
console.log('NO');
}
结果 false
if([1]){
console.log([1]== true);
}else {
console.log('NO');
}
true == 1
结果 true
面试题 09
// Fuction.prototype 是匿名函数
function f(){}
var parent = Object.getPrototypeOf(f);
console.log(f.name);//f
console.log(parent.name);//''
}
面试题 10
(function(){
var x = y = 1;
})()
console.log(y); //能够获取y的值吗? 1
console.log(x); //能够获取x的值吗? 报错
设计模式简单说明
设计模式 ---> 解决问题的套路
在开发中总结的一套方法,专门用来解决一类问题
要求:设计一套系统需要设计模式(架构师)
-
来源: 建筑行业
- 设计模式的四人帮
常见的设计模式(23): 单粒(例)模式, 代理委托模式,观察者模式,中介模式...
<<设计模式>> , <<大话设计模式>>,<<大话数据结构>>
编程就是: 数据结构 + 算法
==工厂模式==
- 核心步骤:
- 1.提供一个父构造函数(开了一家工厂)
- 2.设置父构造函数的原型对象(产品公共的一些东西)
- 3.在父构造函数上提供一个静态的工厂方法(生产产品)
- 4.定制合作伙伴
- 5.使用父构造函数的静态工厂方法创建对象
1.提供一个父构造函数(开了一家工厂) function PhoneMake (){ } 2.设置父构造函数的原型对象(产品公共的一些东西) PhoneMake.prototype.logDes = function (){ } 3.在父构造函数上提供一个静态的工厂方法(生产产品) PhoneMake.factory = function (){ console.log(this.des) } 4.定制合作伙伴 PhoneMake.iphone = function(){ this.des = '' } PhoneMake.vivo = function(){ this.des = '' PhoneMake.oppo = function(){ this.des = '' } 5.使用父构造函数的静态工厂方法创建对象 var iphone = PhoneMake.factory('iPhone'); iphone.logDes(); var vivo = PhoneMake.factory('vivo'); vivo.logDes(); var oppo = PhoneMake.factory('oppo'); oppo.logDes(); var meizu = PhoneMake.factory('meizu'); meizu.logDes();