1.定义匿名函数:
<script type="text/javascript">
var f = function (name){
document.writeln('匿名函数<br/>');
document.writeln('你好' + name) ;
};
f('china') ;
</script>
2.继承:
1)原型链继承:
让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性。
当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
function Parent() {
this.isShow = true
this.info = {
name: "mjy",
age: 18,
};
}
Parent.prototype.getInfo = function() {
console.log(this.info);
console.log(this.isShow);
}
function Child() {};
Child.prototype = new Parent();
let Child1 = new Child();
Child1.info.gender = "男";
Child1.getInfo(); // {name: 'mjy', age: 18, gender: '男'} ture
let child2 = new Child();
child2.isShow = false
console.log(child2.info.gender) // 男
child2.getInfo(); // {name: 'mjy', age: 18, gender: '男'} false
优点:写法方便简洁,容易理解。
缺点:对象实例共享所有继承的属性和方法。传教子类型实例的时候,不能传递参数,因为这个对象是一次性创建的(没办法定制化)。
2.借用构造函数继承
function Parent(gender) {
this.info = {
name: "yhd",
age: 19,
gender: gender
}
}
function Child(gender) {
Parent.call(this, gender)
}
let child1 = new Child('男');
child1.info.nickname = 'xiaoma'
console.log(child1.info);
let child2 = new Child('女');
console.log(child2.info);
在子类型构造函数的内部调用父类型构造函数;使用 apply()
或 call() 方法将父对象的构造函数绑定在子对象上。
优点:解决了原型链实现继承的不能传参的问题和父类的原
型共享的问题。
缺点:借用构造函数的缺点是方法都在构造函数中定义,因此无法实现函数复用。在父类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。
3.组合继承(经典继承)
function Person(gender) {
console.log('执行次数');
this.info = {
name: "mjy",
age: 19,
gender: gender
}
}
Person.prototype.getInfo = function () { // 使用原型链继承原型上的属性和方法
console.log(this.info.name, this.info.age)
}
function Child(gender) {
Person.call(this, gender) // 使用构造函数法传递参数
}
Child.prototype = new Person()
let child1 = new Child('男');
child1.info.nickname = 'xiaoma'
child1.getInfo()
console.log(child1.info);
let child2 = new Child('女');
console.log(child2.info);
优点: 解决了原型链继承和借用构造函数继承造成的影响。
缺点: 无论在什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数
内部
4.原型式继承
方法一:
借用构造函数在一个函数A内部创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。
本质上,函数A是对传入的对象执行了一次浅复制。
function createObject(obj) {
function Fun() {}
Fun.prototype = obj
return new Fun()
}
let person = {
name: 'mjy',
age: 18,
hoby: ['唱', '跳'],
showName() {
console.log('my name is:', this.name)
}
}
let child1 = createObject(person)
child1.name = 'xxxy'
child1.hoby.push('rap')
let child2 = createObject(person)
console.log(child1)
console.log(child2)
console.log(person.hoby) // ['唱', '跳', 'rap']
方法二:Object.create()
Object.create() 是把现有对象的属性,挂到新建对象的原型上,新建对象为空对象
ECMAScript 5通过增加Object.create()方法将原型式继承的概念规范化了。这个方法接收两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)。在只有一个参数时,Object.create()与这里的函数A方法效果相同。
let person = {
name: 'mjy',
age: 19,
hoby: ['唱', '跳'],
showName() {
console.log('my name is: ', this.name)
}
}
let child1 = Object.create(person)
child1.name = 'xxt'
child1.hoby.push('rap')
let child2 = Object.create(person)
console.log(child1)//
console.log(child2)//
console.log(person.hoby) // ['唱', '跳', 'rap']
变量提升 函数提升
console.log(a);
var a=6;
简单说就是在js代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端。
也就是说刚才的代码,js的执行过程其实是这样的:
var a;
console.log(a)
a=6;
js的var关键字把变量声明,提升到了最顶端,然后才去执行剩下的编译代码,这也是最基本的变量提升案例了。
注意:变量提升只提升声明,不提升赋值
function chifan(){
console.log('我要吃米饭')
}
chifan()
function chifan(){
console.log('我要吃面')
}
chifan()
变为:
var chifan=function (){
console.log('我要吃米饭')
}
var chifan=function (){
console.log('我要吃面')
}
chifan()
chifan()
这就是所谓的js的函数提升,我们使用的是函数声明的方式,所以js会有类似于变量提升的函数提升,与变量提升不同,函数提升不仅仅提升函数声明,而是提升函数整体
var game=function (){
console.log('玩英雄联盟')
}
game()
var game=function (){
console.log('玩CSGO')
}
game()
这里并没有用函数声明的方式,而用的是函数表达式的方式,所以并不存在函数整体提升,仅仅也只是声明提升,具体执行过程如下:
var game
var game
game=function (){
console.log('玩英雄联盟')
}
game()
game=function (){
console.log('玩CSGO')
}
game()
类的特性
类是用于创建对象的模板。他们用代码封装数据以处理该数据。JS 中的类建立在原型上,但也具有某些语法和语义未与 ES5 类相似语义共享。
实际上,类是“特殊的函数”,就像你能够定义的函数表达式和函数声明一样,类语法有两个组成部分:类表达式和类声明。
类的声明:class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
函数声明和类声明之间的一个重要区别在于,函数声明会提升,类声明不会。你首先需要声明你的类,然后再访问它,否则类似以下的代码将抛出ReferenceError:
letp =newRectangle();// ReferenceError
classRectangle{}
类表达式是定义类的另一种方法。类表达式可以命名或不命名。命名类表达式的名称是该类体的局部名称。(不过,可以通过类的 (而不是一个实例的) name 属性来检索它)。
// 未命名/匿名类
let Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
// output: "Rectangle"
// 命名类
let Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
console.log(Rectangle.name);
// 输出:"Rectangle2"
类的修饰符有什么作用
- public:公开的,谁都能用(默认就是 public)
- private:私有的,仅类自己能使用,子类与外部都不能使用
- protected:受保护的,仅类和类的子类能使用,外部不能使用
- readonly:只能读不能写
readonly 只能在 constructor 构造方法初始化时赋值,或者声明时赋值,之后都不能在修改值。
class Person{
readonly name: string
// 构造初始化赋值
constructor(name: string) {
this.name = name
}
}
- static:静态成员无需实例化,直接通过类名调用
网络操作
1)xhr/fetch
1.xhr:在Fetch出现之前我们发送异步请求默认都是通过ajax,底层使用了宿主环境的(XHR)XMLHTTPRequest 对象来实现异步请
求。实现代码如下:
//获取元素
const result = document.getElementById('result') | |
//绑定事件 | |
result.addEventListener('mouseover',function(){ | |
//1.创建对象 | |
const xhr = new XMLHttpRequest(); | |
//2.初始化 设置类型与 URL | |
xhr.open('POST','http://127.0.0.1:8000/server'); | |
//设置请求头 | |
// xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); | |
xhr.setRequestHeader('name','zz'); | |
//3.发送 | |
xhr.send('a=100&b=200&c=300'); | |
// xhr.send('a:100&b:200&c:300'); | |
// xhr.send('123456789'); | |
//4.事件绑定 | |
xhr.onreadystatechange = function(){ | |
//判断 | |
if(xhr.readyState === 4){ | |
if(xhr.status>=200 && xhr.status <300){ | |
//处理服务端返回的结果 | |
result.innerHTML = xhr.response; | |
} | |
} | |
} | |
}) |
2.fetch:是一个API 是在ES6出现的 它使用ES6提出的Promise对象 是XMLHttpRequest的替代品 最大的特点就是 通过数据流对象处理数据 可以提高网站性能,它还提供了一个全局 fetch()方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。
fetch('http://example.com/movies.json')
.then(function(response) {
return response
})
.then(function(response) {
console.log(response);
});
但是:
1.fetch是有兼容问题的
IE系列是完全不支持的,主流浏览器的早起版本也不支持,所以
如果在项目中使用需要做兼容方案处理。
2.fetch 不管请求处理成功还是失败,都会触发promise的resolve状态回掉。这个和传统的ajax 框架是有点区别的。fetch只有当网络故障导致请求发送失败或者跨域的时候才会触发reject的逻辑。我们可以通过response 对象的ok是否是true来判断是否是真正的成功。
3.fetch配置请求是否携带cookie和接受服务端写入cookie是通过设
置credentials
fetch('/users.json', {
method: 'POST',
body: JSON.stringify({
email: 'huang@163.com'
name: 'jim'
})
}).then(function() { /* 处理响应 */ });
url参数是必须要填写的,option可选,设置fetch调用时的Request对象,如method、headers等
比较常用的Request对象有:
- method - 支持 GET, POST, PUT, DELETE, HEAD
- url - 请求的 URL
- headers - 对应的 Headers 对象
- body - 请求参数(JSON.stringify 过的字符串或’name=jim\u0026age=22’ 格式)