Giter Club home page Giter Club logo

blog's People

Contributors

likaixuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

blog's Issues

深入浅出谈Promise.md

Promise是异步编程的一种解决方案,可以帮助我们解决回调地狱的问题,网络上有很多这方面的教程,但都很晦涩难懂,本文尽可能让大家更容易的理解promise

ES6规定,Promise对象是一个构造函数,用来生成Promise实例。

基本使用

1.我们直接上代码,看看运行结果

var Obj=new Promise(function(){
    console.log("hello 凯旋");
});
//hello 凯旋

Promise构造函数接受一个函数当做参数,而且创建后会立即执行这个函数

2.有了对上面那些粗浅的认识,我们现在就可以完成一个回调的案例(这只是我的一个恶趣味(逃····)
有三个方法t1、t2、t3 ,要求 t1执行完后执行t2,t2执行完后执行t3

//正常来说是这样去做 t1(t2(t3))
function t1(){
    console.log("老子是t1");
    return new Promise(t2);
}
function t2(){
    console.log("老子是t2");
    return new Promise(t3);
}
function t3(){
    console.log("老子是t3");
}
new Promise(t1);//依次执行 t1、t2、t3 

这个案例就是借助了 Promise创建后会立即执行这个特点 接下来我们开始正经的说说Promise

3.上面说了Promise构造函数接受一个函数当参数 也就是这样

var Obj=new Promise(function(){});

但其实这个函数也接收两个参数

var promise = new Promise(function(resolve, reject) {})

这两个参数分别是resolve和reject。它们是两个函数,这俩函数是JavaScript引擎提供的,不用咱们自己管。
那么他们是干啥的,我们看案例

var promise = new Promise(function(resolve, reject) {
    setTimeout(function(){
        resolve("我是数据");
    },3000);
})
promise.then(function(data){
    console.log(data);
});

运行后发现 三秒后会打印 我是数据 那么这是咋回事呢
Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

上面的字好长啊,实际浓缩一下就是这样 我们调用 resolve这个方法的时候 就说明我们这个操作完成了 它会触发promise.then这个方法 这个方法实际上也有俩参数(可以只写一个),也是俩函数,第一个是 当执行resolve后 调用的,第二个是执行reject时候调用的, 这俩函数的参数就是调用resolve和reject时传过来的值

4.来看个案例吧 这么多字写的我也头疼

var promise = new Promise(function(resolve, reject) {
    setTimeout(function(){
        reject("我是错误");
    },3000);
})
promise.then(function(data){
    console.log(data);
},function(error){
    console.log(error)
});

上面代码就会打印出 我是错误
5.then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行

var promise = new Promise(function(resolve, reject) { 
    console.log('Promise'); resolve();
});
promise.then(function() { 
    console.log('Resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// Resolved

6.then的链式操作 案例

function t1() {
    var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("t1");
    }, 1000);
    });
    return promise;
}
function t2() {
    var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("t2");
    }, 1000);
    });
    return promise;
}
function t3() {
    var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("t3");
    }, 1000);
    });
    return promise;
}
t1().then(function(data) {
    console.log(data);
    return t2();
}).then(function(data) {
    console.log(data);
    return t3();
}).then(function(data) {
    console.log(data);
});

每一次调用then必须返回一个新的promise来实现这个链式调用

catch

其实它和then的第二个参数一样,用来指定reject的回调

function t1() {
    var promise = new Promise(function(resolve, reject) {
        setTimeout(function() {
            reject("出错了");
        }, 1000);
  });
  return promise;
}
t1().then(function(data) {
    console.log(data);
    return t2();
}).catch(function(error){
    console.log(error)
 }
);
我们没有指定reject回调的时候 就执行它 它还有个功能就是 假设我们执行了resolve的回调 里面出错了 它不会中断执行 而是进入catch 

all与race

1.arr的基本使用

function t1() {
    var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("t1");
    }, 1000);
    });
    return promise;
}
function t2() {
    var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("t2");
    }, 2000);
    });
    return promise;
}
function t3() {
    var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
        resolve("t3");
    }, 3000);
    });
    return promise;
}
Promise.all([t1(), t2(), t3()]).then(function(results) {
    console.log(results);
});
//["t1", "t2", "t3"]

其实就是等所有的异步操作做完,才执行when 而且返回的是个数组(所有异步操作的)
race与all不同之处就是在于 谁先完成这个异步操作,谁就执行when操作 返回的是最先完成异步操作的

javascript 构造器属性(constructor)

当我们创建对象时,实际上也同时赋予了该对象构造器属性 constructor,该属性是创建该对象的构造函数的引用

  1. 声明一个构造函数
//声明一个构造函数 构造函数首字母应大写
function Obj(name){
	this.name=name;
	this.fun=function(){
		alert(this.name);
	}
}
  1. 用Obj构造函数创建一个对象
var testObj=new Obj("李凯旋");//调用方法 打印 传递过去的值 即为”李凯旋“
testObj.fun();//弹出"李凯旋"

正如我们开始时所说:”当我们创建对象时,实际上也同时赋予了该对象构造器属性 constructor,该属性指向用于创建该对象的构造函数的引用“,我们现在来打印一下这个构造器属性

3.打印一下构造器属性

alert(testObj.constructor)//弹出的就是Obj这个构造函数、由此可见constructor属性指向创建此对象的构造函数本身

4.再次验证

//声明一个构造函数 构造函数首字母应大写
function Obj(name){
	this.name=name;
	this.fun=function(){
		alert(this.name);
	}
}
var testObj=new Obj("李凯旋");
testObj.fun();//弹出"李凯旋"
//通过testObj.constructor来创建一个对象
var testObj2=new testObj.constructor("我是通过testObj指向的构造函数创建的");
testObj2.fun();//弹出"我是通过testObj指向的构造函数创建的"
alert(testObj.constructor===testObj2.constructor);//弹出true 说明两个对象全等于它们是从一个构造函数上创建的

5.字面量方式创建对象也是由object构造函数创建的

var test={
	name:"李凯旋"
};
alert(test.constructor);//会弹出function object();

javascript arguments、callee、caller的基本使用.md

arguments、calle、caller基本使用

本文是作者的学习笔记、主要是给大家说说callee与caller的简单使用、有不足之处在所难免欢迎大家指正。

arguments介绍

我们在使用javascript 函数(function)的过程中,往往会指定函数的参数(形参)

function fun(f1){
	console.log(f1);		
}

也可以不指定函数的参数

function fun(){
	console.log("hello 凯旋");
}

但其实javascript是不对函数传参个数进行语法检查的

function fun(f1){
	console.log(f1);		
}
fun(); //undefined

我们并没有给fun传参、运行也没有任何的语法错误提示、只是告诉我们 undefined
如果一个函数有形参但是实际调用时没有传递参数那么也不影响程序运行、只是我们没法使用这个参数而已

但如果我们传递的参数多于形参呢?

function fun(f1){
	console.log(f1);		
}
fun(1,2);  // 1

也不会有任何报错、只不过我们无法使用多出的参数而已

但其实javascript提供了一个对象、没错那就是arguments、我们先来使用它

function fun(f1){
	console.log(f1);
	console.log(arguments[0]);
	console.log(arguments[1]);	
}
fun(1,2);  // 1 1 2

arguments和数组类似但不是数组、它保存着函数调用时传递过来的所有参数、下标从0开始顺序接收

一方更改也立即作用到另一方

function fun(f1){
arguments[0]=5;
	console.log(f1);
	f1='hello';
	console.log(arguments[0]);
}
fun(1,2);  // 5 hello

arguments还可以帮助我们在javascript中实现函数重载

function fun(f1) {
		if(arguments.length === 1) {
			console.log("我是一个参数的fun:"+arguments[0]);
		} else if(arguments.length === 2) {
			console.log("我是两个参数的fun:"+arguments[0]+arguments[1]);
		} else if(arguments.length === 3) {
			console.log("我是三个参数的fun:"+arguments[0]+arguments[1]+arguments[2]);
		} else{
			console.log("参数太多啦");
		}
				
}
fun(1,"kx");//我是两个参数的fun:1 kx

arguments对象不是一个Array、它类似于Array,但不具有除了length方法的任何方法,例如 sort方法、pop方法等
但它可以被转换为一个真正的Array(想要了解可以去自行查阅原型、call等方面的知识):

var arr = Array.prototype.slice.call(arguments);

callee介绍

我们还可以用arguments来干什么呢?那我们就不得不提到callee了

callee是arguments对象的一个属性、用来指向当前执行的函数。

function fun() {
	console.log(arguments.callee);
}
fun();//fun() { console.log(arguments.callee);}

返回的就是fun函数本身

我们还可以用它来验证传入的参数是否与形参相等

function fun(fun1,fun2){
	if(arguments.length===arguments.callee.length){//function对象的length属性返回的是参数个数
		console.log("参数正确");
	} else{
		console.log("参数不正确");
	}
}
fun(1,1);

callee还可以用来递归调用匿名函数

(function(){
	alert(1);
	arguments.callee();
})();

哈哈、这是一个死循环了

caller介绍

接下来我们再来谈谈caller、直接用用看吧

function fun1(){
console.log(arguments.callee.caller);
}
function fun2(){
	fun1();
}
fun1();
fun2();// null  function fun2() {fun1();}

caller是function对象的一个属性用于返回一个function引用、它返回调用它的function对象、若直接在全局环境下调用fun1 则返回null、在fun2里调用之后返回fun2、

本文完、若有错误欢迎指出

javascript 作用域

javascript 作用域

本文主要是给大家说说作用域在javascript中是怎么一回事、有不足之处在所难免欢迎大家指正。

函数作用域

JavaScript 不是块级作用域而是通过函数来管理作用域,在函数内部声明的变量只能在这个函数内部使用,

1.块级作用域测试

if(true){
	var test=1;
}
console.log(test); //1

2.函数级作用域测试

(function() {
	var test = 1;
})();
console.log(test); //Uncaught ReferenceError: test is not defined

通过上面两个例子我们可以看出 在函数里声明的变量在外边是不能用的、而块级是可以的

全局变量

全局变量是在函数外定义的变量或者未定义就使用的变量(隐式全局变量)又或是直接用window.属性名=值添加的变量,每一个javascript运行环境都有一个全局对象,例如在浏览器中window就指向这个全局对象(nodeJS是global),其实我们创建的每一个全局变量或者全局方法都是全局对象的一个属性和方法

var a=5;
(function(){
	console.log(a);
	console.log(window.a);
})();//5 5

由此可见 全局变量其实就是全局对象上的一个属性、我们甚至可以通过window来添加一个全局变量

(function(){
	window.a=7;
})();
console.log(a);//7

全局变量添加成功啦 ^_^

隐式全局变量

在javascript中不用声明就能使用变量、而且没有声明就使用的变量也会默认成为全局对象的属性

(function(){
	a=7;
})();
console.log(a);//7

这就很尴尬了,既然直接用就是全局变量,那么我们为啥还要用var来定义全局变量,它们之间到底有啥区别?
听我慢慢说来:
1.没有用var 声明就使用的变量在严格模式下会报错的

"use strict";
a=1;
console.log(a);//Uncaught ReferenceError: a is not defined

2 var声明的全局变量会被提升,隐式全局变量不会被提升(提升一会就会说到)

未提升

console.log(a);//Uncaught ReferenceError: a is not defined
a=1;

提升

console.log(a);// undefined
var a=1;

3 var声明的全局变量不可用delete删除、隐式全局变量可以

var a=1;
b=2;
delete a;
delete b;
console.log(a);//1
console.log(b);////Uncaught ReferenceError: b is not defined

变量提升

在Javascript中,函数及变量的声明都将被提升到函数的最顶部,也就是说我们可以先使用后声明,
但函数表达式和变量表达式只是将函数或者变量的声明提升到函数顶部,函数表达式和变量的初始化将不被提升我们来看一下案例

fun();//hello,world哥
function fun(){
	console.log("hello,world哥");
}

方法先使用后声明这显然是没有问题的、那么我们接着看变量的提升

console.log(a);//undefined
console.log(b);//Uncaught ReferenceError: b is not defined
var a=5;

a的声明被提升,但是初始化值并没有提升、打印a的值为undefined、说明有这个变量但是它没有值、没有声明的b直接报了错,说明变量的声明是会提升的但是变量的初始化不会提升

我们接着来看

var fun=function(){
console.log("本事啦,我的弟");
}
fun();//本事啦,我的弟

显然没有任何问题,我们把声明和使用颠倒位置

fun();
var fun=function(){
	console.log("本事啦,我的弟");//Uncaught TypeError: fun is not a function
}

我们发现报错了,但如果我们直接使用fun则会报一个"Uncaught ReferenceError: fun is not defined"的错误(和不声明fun报错是不一样的),其实fun也是一个变量,只不过他是function(){console.log("本事啦,我的弟");}的一个引用,fun的声明被提升了,但是初始化没有被提升。

再给大家来一个比较有趣的关于提升的例子

var a=1;
(function(){
	console.log(a);
	var a=2;
	console.log(a);
})();

大家认真的思考一下、打印结果是什么?
正确答案:undefined 2 大家应该想的是1,2 其实这个结果就是变量提升的原因
###词法作用域
在javascript中每个函数都有一个属于自己的词法作用域,在定义时而非执行时都会创建一个自己的作用域

function fun1(){var a=1;fun2();}
function fun2(){return a;}
fun1();//Uncaught ReferenceError: a is not defined

大家应该想的是返回1吧,报错的原因是在fun2定义时(而非执行时),a是不可见的,它只能访问自身作用域和全局作用域,如果大家还是不明白那么可以仔细想想 这句话 "在定义时而非执行时都会创建一个自己的作用域"

javascript 存储器属性

参考

1.javascript权威指南
2.javascript高级程序设计
3.MDN

概念

对象属性分为两种:一种就是平常用的 数据属性
例如

var obj = {
  title:"凯旋哥哥好帅啊"
}

还有一种就比较怪异且强大了,那就是存取器属性(权威指南的叫法)

var obj={
  get title(){
    return "我是一个标题"
  },
  set title(n){
    console.log(n+"好帅啊");
  }
}
obj.title="凯旋哥哥";
console.log(obj.title);
//凯旋哥哥好帅啊
//我是一个标题

我们用get和set来定义title,当我们读取title时(obj.title)就会执行get的函数体,return就是title的值。对title进行设置时(obj.title="凯旋哥哥") 就会执行set的函数体,而且赋值号右边的值会当做参数传入set函数体,可以忽略set函数体的返回值。
存储器属性也可以被继承

  var obj={
        get title(){
              return "我是一个标题"
        },
        set title(n){
              console.log(n+"好帅啊");
        }
   }
  var son={};
  son.__proto__=obj;
  son.title="凯旋哥哥";
  console.log(son.title);
//凯旋哥哥好帅啊
//我是一个标题

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.