首页
登录
搜索
登录
搜索
emer
累计撰写
197
篇文章
累计收到
496
条评论
首页
栏目
首页
登录
自定义幻灯片
最新文章
2019-11-8
JavaScript中的字符串模版
我个人认为这个功能并不是那么简单。 可能有更多实用的功能我只是没有发现。 如果只是那么简单这个功能有点... let user_type = 'ordinary'; function handle(strings, type) { // 这里指的注意的是第一个参数是个数组,将所有的字符串常量被变量分割的收集起来,第二个参数是一个变量,可以有多个变量对应的有多个参数 let output = strings[0]; let varstr; if (type == 'ordinary') { varstr = '单价是100元人民币'; }else { varstr = '批发价是50元人民币'; } return `${output}${varstr}` } let show = handle`您购买的商品${user_type}` console.log(show)
2019年-11月-8日
39 阅读
0 评论
未分类
2019-11-5
ES5、ES6中的参数默认值
在ES5中设置默认值是十分麻烦的一件事情 大家看一下,了解就好 function add(x, y, z) { if (y === undefined) { y = 12 } if (z === undefined) { z = 20 } return x + y + z; } add(1) // return 33 大家再来看ES6中的默认值处理方式 function add (x, y = 10, z = 20) { return x + y + z } add(3) // reutrn 33
2019年-11月-5日
42 阅读
0 评论
未分类
2019-11-5
深入理解JavaScript中的class
Class Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类)。 这是摘自阮一峰老师的博客,这句话放在 ES5 可以说不为过,然而到了 ES6 这么说就已经不严谨了。因为 ES6 中已经有了专属的 class 语法了。 有的同学喜欢函数式的编程方式,有的同学喜欢面向对象的编程思维,我们今天不论长短,重点讲述怎么使用 ES6 的 class 语法完成面向对象的开发。 Intro 对于面向对象编程而言,更关注类的声明、属性、方法、静态方法、继承、多态、私有属性。 Basic Syntax 首先我们要先来说明在 JavaScript 世界里如何声明一个 “类”。在 ES6 之前大家都是这么做的: let Animal = function (type) { this.type = type this.walk = function () { console.log(`I am walking`) } } let dog = new Animal('dog') let monkey = new Animal('monkey') 在上述代码中,我们定义了一个叫 Animal 的类,类中声明了一个属性 type、一个方法 walk;然后通过 new Animal 这个类生成实例,完成了类的定义和实例化。当然你也可以这样写: let Animal = function (type) { this.type = type } Animal.prototype.walk = function () { console.log(`I am walking`) } let dog = new Animal('dog') let monkey = new Animal('monkey') 在 ES6 中把类的声明专业化了,不在用 function 的方式了,请看: class Animal { constructor (type) { this.type = type } walk () { console.log(`I am walking`) } } let dog = new Animal('dog') let monkey = new Animal('monkey') 很明显,从定义上就很专业了,有构造函数、方法,但是 ES6 增加了新的数据类型 class 吗? console.log(typeof Animal); //function 可以发现 class 的类型还是 function,和 ES5 貌似并没有什么区别,那么 class 中定义的方法在哪呢?我们知道只要是函数,就一定会有 prototype 对象。那么类的方法和 prototype 对象有什么关系呢? console.log(Animal.prototype); // {constructor: ƒ, walk: ƒ} // constructor: class Animal // walk: ƒ walk() // __proto__: // constructor: ƒ Object() // hasOwnProperty: ƒ hasOwnProperty() // isPrototypeOf: ƒ isPrototypeOf() // propertyIsEnumerable: ƒ propertyIsEnumerable() // toLocaleString: ƒ toLocaleString() // toString: ƒ toString() // valueOf: ƒ valueOf() // __defineGetter__: ƒ __defineGetter__() // __defineSetter__: ƒ __defineSetter__() // __lookupGetter__: ƒ __lookupGetter__() // __lookupSetter__: ƒ __lookupSetter__() // get __proto__: ƒ __proto__() // set __proto__: ƒ __proto__() 可以看出在 Animal.prototype 对象上有两个方法,一个是构造函数(constructor)、一个是自定义的方法(walk)。这是不是和 ES5 的第二种写法一模一样?我们再来看下属性,在 ES5 中有个 API 用来判断对象的自有属性(hasOwnProperty)。 console.log(dog.hasOwnProperty('type')); //true 这个表现也和 ES5 中直接使用 function 定义类的方式相同,所以得出一个结论:class 的方式是 function 方式的语法糖。 Setters & Getters 对于类中的属性,可以直接在 constructor 中通过 this 直接定义,还可以直接在类的顶层来定义: class Animal { constructor (type, age) { this.type = type this._age = age } get age () { return this._age } set age (val) { this._age = val } } 这个代码演示了,通过 get/set 来给类定一个属性,不过貌似没有说服力。因为 age 和 _age 都是类的属性,而且是相同的含义这样做感觉没有实际用途。但是如果一个属性是个只读的呢? class Animal { constructor (type) { this.type = type } get addr () { return '北京动物园' } } 毋庸赘述,大家都能看出来含义。再来看下如下的应用场景: class CustomHTMLElement { constructor (element) { this.element = element } get html () { return this.element.innerHTML } set html (value) { this.element.innerHTML = value } } 利用 set/get 实现了对 element.innerHTML 的简单封装。 可是,有时候我们真的需要设置一个私有属性(闭包),然后通过一定的规则来限制对它的修改,利用 set/get就可以轻松实现。 let #age = 1 class Animal { constructor(type) { this.type = type } get age() { return #age } set age(val) { if (val > 0 && val < 10) { #age = val } } } Static Methods 静态方法是面向对象最常用的功能,在 ES5 中利用 function 实现的类是这样实现一个静态方法的。 let Animal = function (type) { this.type = type this.walk = function () { console.log(`I am walking`) } } Animal.eat = function (food) { console.log(`I am eating`); } 在 ES6 中使用 static 的标记是不是静态方法,代码如下: class Animal { constructor (type) { this.type = type } walk () { console.log(`I am walking`) } static eat () { console.log(`I am eating`) } } 有没有很清爽,代码可读性一下子就上来了。 Sub Classes 面向对象只所以可以应对复杂的项目实现,很大程度上要归功于继承。如果对继承概念不熟悉的同学,可以自行查询。在 ES5 中怎么实现继承呢? // 定义父类 let Animal = function (type) { this.type = type } // 定义方法 Animal.prototype.walk = function () { console.log(`I am walking`) } // 定义静态方法 Animal.eat = function (food) { console.log(`I am eating`) } // 定义子类 let Dog = function () { // 初始化父类 Animal.call(this, 'dog') this.run = function () { console.log('I can run') } } // 继承 Dog.prototype = Animal.prototype 从代码上看,是不是很繁琐?而且阅读性也较差。再看看 ES6 是怎么解决这些问题的: class Animal { constructor (type) { this.type = type } walk () { console.log(`I am walking`) } static eat () { console.log(`I am eating`) } } class Dog extends Animal { constructor () { super('dog') } run () { console.log('I can run') } } 虽然 ES6 在类的定义上仅是 ES5 定义类的语法糖,但是从开发者的角度而言,开发更有效率了,代码可阅读性大大提升。 练习 请实现一个堆栈类,具备 push、pop 功能。 请回忆下自己在业务中有哪些场景可以用类来实现。
2019年-11月-5日
48 阅读
0 评论
未分类
2019-11-5
ES6中类的继承
相比ES5中类的继承ES6中类的继承语法更加简单明了 class Animal { constructor(type) { this.type = type } eat () { console.log(`我是small ${this.type},我要吃`) } } class Dog extends Animal {} let dog = new Dog('dog') dog.eat() // 输出 我是small dog,我要吃 在看下面一个example class Animal { constructor(type) { this.type = type } eat () { console.log(`我是small ${this.type},我要吃`) } } class Dog extends Animal { constructor(type, age) { super(type) this.age = age } say() { console.log(`我快${this.age}岁了`) } } let dog = new Dog('dog', 2) dog.eat() dog.age()
2019年-11月-5日
58 阅读
0 评论
未分类
2019-11-5
ES5中类的继承
ES5中类的继承实现相对是比较麻烦的 let Animal = function (type) { this.type = type } Animal.prototype.eat = function () { console.log('我要吃') } let Dog = function () { Animal.call(this, 'dog') } Dog.prototype = Animal.prototype let dog = new Dog() dog.eat() 这里需要说明的是call(this, args) call是指将Animal中的this指向Dog类中
2019年-11月-5日
47 阅读
0 评论
未分类
2019-11-5
ES6中的静态方法
相比在ES5中的静态方法ES6定义的更加清晰,在ES6中定义一个静态方法只需要一个static关键字 下面请看example class Animal { constructor(type) { this.type = type } eat () { Animal.walk() console.log('我在吃') } static walk() { console.log('我要走过去') } } (new Animal('小狗')).eat()
2019年-11月-5日
39 阅读
0 评论
未分类
2019-11-5
ES5中的静态方法
静态方法是什么? 静态方法是指一个类的方法。通过类的实例调用这个方法是调用不到的。 只能通过类调用 下面看一下例子 let Animal = function (type) { this.type = type } Animal.prototype.eat = function () { Animal.walk() console.log('我在吃东西') } Animal.walk = function () { console.log('先走了过去') } let dog = Animal('dog') dog.eat() 代码解读,首先我申明了一个类。 在类的原型上我定义了一个方法 而后在类上我定义了一个walk的方法 注意⚠️定义在类上面的方法只能通过类来调用 最后我在eat方法中调用了这个walk 运行程序执行成功 而这时候我如果通过this来调用walk呢? 那么结果是一定的程序会报错
2019年-11月-5日
37 阅读
0 评论
未分类
2019-11-5
关于JavaScript中的getter和setter
在没有ES6 之前如果私有化一个类的属性是的确不易的。不能说ES5完全做不到但是确实是十分费力气的一件事 但是现在在ES6中有getter以及setter将使私有化变得十分容易 大家先看一下例子 let _age = 10; class Animal{ constructor(type) { this.type = type } get age () { return _age; } set age (value) { if (value < 12 && value > 10) { _age = value } } age () { console.log(`${type}在吃饭`) } } let dog = new Animal('小狗') console.log(dog) // 这个时候一定只会输出一个属性那就是type // 我们来看一下age console.log(dog.age) // 这个时候是10 // 我们尝试修改它一下 dog.age = 100 console.log(dog.age ) // 结果我们发现age 并没有改变,这是为什么呢? 通过上面的例子。我们可以看出age的value并没有变为100 因为我们set age的时候加了一个判断条件 这个值必须为11的时候才可以被改变 换句话说这个者其实并不是dog实例中的age。而dog实例中的age 相当于一个入口。而真正意义上的值在_age上面。 还有一个问题为什么我不将age中的值写在this里面呢? 因为语法特性目前还不支持私有。只能以闭包的形式写在上面
2019年-11月-5日
45 阅读
0 评论
未分类
2019-11-5
Django获取URL
下边代码内容是关于Django获取当前页面URL的代码,应该是对小伙伴有所用。 request.get_full_path() 获取不带参数URL request.path 获取主机地址 request.get_host()
2019年-11月-5日
41 阅读
0 评论
未分类
2019-11-5
深入理解Django中间件
一、django生命周期 写中间件之前呢?还是来说说django的生命周期,我再画下图贴上来,比较清楚 1、浏览器向127.0.0.1:8000/index这个url发出一个请求 2、首先网络通信都是基于socket的,那么django一样,通过wsgiref协议来的 3、在socket对来的请求进行一系列处理,将请求带来的数据处理到request对吧 4、然后再走到中间件 5、通过路由层,分发到对应的视图函数, 6、在视图函数中可能会去数据库取数据,到模板层渲染模板好了之后, 7、再通过中间件,再到wsgiref进行处理,返回到浏览器前端 对于模板层,视图层,路由层就十分熟悉不过了,就是多了一个中间件的那一层, 从上面也应该能够知道,前端浏览器来的请求还是我后台django的响应,是不是都要走到中间件那层, 那我们是不是在请求来的时候,先在中间件那里对请求做一些处理,再响应的时候,又做一次处理呢? 二、中间件 下面就说说怎么自定义一个中间件,那应该怎么去定义呢? 不知道的话,那就是去看看django它的中间件是怎么样的,我们跟着写不就好了? 在settings文件有个MIDDLEWARE的变量,它就是装着中间件的列表 MIDDLEWARE = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ] 里面都是字符串,我应该怎么操作才能看到信息(这里可能有点啰嗦,但我还是要写,你知道可能别人不知道吧) 复制其中的一个元素,将它的格式改为下面这种格式 from django.middleware.clickjacking import XFrameOptionsMiddleware # 没错这就是导包的方法,那请问django它内部是怎么处理这个的呢? # 我猜测,只是猜测,无非就是在最前面加form,最后一个小数点改为import,就和上面不就一样了么。 # 然后你再Ctrl+左击鼠标就能进去看源码了 # 额额,再啰嗦一句,怎么看一个对象的源码,首先你要打印type(对象),在终端复制它的class到文件, # 然后操作和上面就是一样了 你多复制几个django自带的中间件,你就会发现,这其实就是一个类,并且继承了MiddlewareMixin这个类, 该类下面的隐藏方法不用去管,就看其他方法有没有相同之处,(这里你最好是自己去操作一下,这样才有印象) 无非就是下面这几个方法: def process_request(self,request) pass def process_response(self,request,response) pass def process_view(self, request, callback, callback_args, callback_kwargs) pass 看名字就应该能知道是干什么的吧,process_request:不就是处理请求嘛,process_response:处理响应。 # 之前讲到浏览器来的请求,django的响应都会走到中间件,那么上面这么方法是不是也会执行到呢? # 如果可以的话,我就可以在中间件控制请求和响应了 三、process_request方法 自定义一个中间件: 1、创建一个py文件,在里面写一个类,继承MiddlewareMixin 2、再到settings里的MIDDLEWARE,添加刚刚创建类 # 注意,1、你别光创建类,然后那么方法就不写了。 2、根据需求写对应的方法,不一定要全部都写。 下面是我写的中间件 zhuyu.py: from django.utils.deprecation import MiddlewareMixin class Test1(MiddlewareMixin): def process_request(self, request): print(‘test1 request zhuyu‘) class Test2(MiddlewareMixin): def process_request(self, request): print(‘test2 request zhuyu‘) settings文件中: MIDDLEWARE = [ ‘django.middleware.security.SecurityMiddleware‘, ‘django.contrib.sessions.middleware.SessionMiddleware‘, ‘django.middleware.common.CommonMiddleware‘, ‘django.middleware.csrf.CsrfViewMiddleware‘, ‘django.contrib.auth.middleware.AuthenticationMiddleware‘, ‘django.contrib.messages.middleware.MessageMiddleware‘, ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘, ‘zhuyu.Test1‘, ‘zhuyu.Test2‘, ] 好了,我现在启动项目,并且发一个请求 如果我没有猜错的话,应该会打印我定义的那两句话 结果毋庸置疑: test1 request zhuyu test2 request zhuyu 我们先看,先打印的是test1,然后才是test2,再去看settings中看看中间件配置 zhuyu.Test1在zhuyu.Test2上方 推断:我们是不是可以判断中间的执行循序是从上到下的呢? 四、process_response方法 process_request方法讲了,那在自定义中间中,再添加process_response def process_response(self,request,response): print (‘test1 response‘) def process_response(self,request,response): print (‘test2 response‘) 这时我们django项目会报错, 错误信息为:‘NoneType‘ object has no attribute ‘get‘ 先不看这个错误,看看我终端的打印情况 打印情况为: test1 request zhuyu test2 request zhuyu test2 response test1 response 分析:前两行的我们知道原因,那为什么第三,四行却是test2,test1呢? 难道不是从上往下的顺序? 解答:首先计算机是不会出问题,出现这种情况,我们只能从结果反推测它怎么运行, 什么时候会走到第三,四行,django处理完数据,响应回前端浏览器,走到中间件, 先走到zhuyu.Test2,再是zhuyu.Test1,那我们就应该知道些什么了 总结:1、浏览器过来的请求,执行顺序是从上往下,依次执行中间件里的process_request方法 2、后台的响应,执行顺序为从下往上,依次执行process_response方法 再说说那个错误:‘NoneType‘ object has no attribute ‘get‘ 分析:出现这个错误是我们在给原先的中间件,添加process_response方法,那肯定是方法那里写的有问题 我们看看那个方法: def process_response(self,request,response): print (‘test2 response‘) 执行该方法的时候,是我们后台已经处理完毕,然后返回到前台浏览器的过程 那这几个参数代表些什么? request:代表request对象,也是前台来的请求对象 response:这个呢?就是我们视图函数返回的HttpResponse对象,你说是不是, 这个对象不应该是从中间件走到wsgiref那里进行处理,再到前台吗? 再看我们的方法,它的返回值是None,所以才会报出上面那个错误 解决方法:让这个方法的返回值是response就好了,return response 思考:这个response就是HttpResponse对象,那我们是不是可以在该方法对这个response进行处理, 再 return response 跟着上面的总结继续写: 3、如果执行process_response方法,必须返回response这个参数 你是不是有这样的一个疑问? 为什么我process_request方法,它的返回值是None,为什么不会出错呢? 好吧!这其实是我疑问,为了解决这个疑问,我去看了它的父类MiddlewareMixin 下面是该类的代码: class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, ‘process_request‘): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, ‘process_response‘): response = self.process_response(request, response) return response 看到这段代码我大概知道中间件是怎么去执行的了,(这里我不太确定yy的对不对) 1、首先settings中MIDDLEWARE是一个列表(也就是可迭代的),那应该就是对MIDDLEWARE进行for循环 2、每循环出一个元素,这里是一个字符串,怎么知道到对应的类呢?我猜应该是和上面上个方法一样,对字符串进行修改 3、找到......................................................... 4、这里我卡住了,我知道大概顺序,但是不知道其内部到底怎么运行,难受,其实就是反射,__call__方法,哎,难弄!!! 5、抽空还是用弄清楚。。卡在这里不舒服,知道的话可以邮件我1923790430@qq.com 6、这里1,2的推断失效! 五、process_view方法 process_view(self, request, callback, callback_args, callback_kwargs) # 这里的request就是和视图函数的request一样 # callback,该request中的url对应的视图函数 # callback_args, callback_kwargs 该试图函数的有名参数,无名参数 # 你也可以在这里调用,其实没多大的意义 # 继续接着创建的中间件添加该方法,看看执行顺序 process_view(self, request, callback, callback_args, callback_kwargs): print (‘test1 view‘) process_view(self, request, callback, callback_args, callback_kwargs): print (‘test2 view‘) 执行看看效果: test1 request zhuyu test2 request zhuyu test1 view test2 view test2 response test1 response 继续测试,我访问127.0.0.1:8000/index,并且在视图函数打印index,再看执行顺序 test1 request zhuyu test2 request zhuyu test1 view test2 view index test2 response test1 response 基于上面的测试,总结下执行顺序: process_request----->process_view----->执行视图函数----->process_response 六、再看process_request方法 它的返回值只能是是HttpResponse对象和None,None代表继续走下一个中间件的process_request方法, 如果是HttpResponse,则会执行当前的process_response方法,相当于跳过了process_view和视图函数那块, 为什么说只能是HttpResponse对象和None,因为有一层判断,判断process_request的返回值,为真的话,拿着 该返回值HttpResponse执行process_response方法,因为process_response方法的参数必须为HttpResponse def __call__(self, request): response = None if hasattr(self, ‘process_request‘): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, ‘process_response‘): response = self.process_response(request, response) return response 这就是上面的依据,get_response这个方法我猜测一定是一直执行各个中间件的process_request,里面肯定是对象的 调用,所以才会继续执行这个__call__方法,执行完所有process_request之后,再从最后一个中间件慢慢往上执行 process_response。 七、process_exception方法 process_exception(self, request, exception) request这个就不再说了 exception是视图函数异常产生的Exception对象。 这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象 ,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个 中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。 八、process_template_response 该方法对视图函数返回值有要求,必须是一个含有render方法类的对象,才会执行此方法 class Test: def __init__(self,status,msg): self.status=status self.msg=msg def render(self): import json dic={‘status‘:self.status,‘msg‘:self.msg} return HttpResponse(json.dumps(dic)) def index(response): return Test(True,‘测试‘)
2019年-11月-5日
98 阅读
0 评论
未分类
4
5
6
7
8