同var一样
let a;
let b,c,d;
let e = 100;
let f = 521,g = 'jll',h=[];
console.log(song); let song = '恋爱达人'
;会报错,而var存在变量提升,则不会报错{
let school = '北京大学';
function fun(){
//虽然fun函数中没有school变量,但会向上查找,因此不影响作用域链
console.log(school);//北京大学
}
fun();
}
const school = '北京大学';
const TEAM = ['WW','EE','RR','YY']
TEAM.push('II');//不会报错
TEAM = 100;//会报错。因为里面的值发生了变化
ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值
const F4 = ['小沈阳','刘能','赵四','宋小宝'];
let [xiao, liu, zhao, song] = F4;//相当于声明了四个变量,每个变量对应的值就是数组的位置
console.log(xiao);//小沈阳
console.log(liu);//刘能
const zhao = {
name:'赵本山',
age:'不详',
xiaopin: function(){
console.log('我可以演小品')
}
}
let {name, age, xiaopin} = zhao;
console.log(name)//赵本山
console.log(age)//不详
xiaopin()//我可以演小品
zhao.xiaopin();
ES6引入新的声明字符串的方式 [``]
let str = `我也是一个字符串哦`;
console.log(str,typeof str);//我也是一个字符串哦 string
es6前
let str = ''
+'沈腾 '
+'马丽 '
+'魏翔 '
+'艾伦 '
+''
//变量拼接
let lovest = '魏翔';
//输出'xxx是我心目中最搞笑的演员'
let result = lovest + ''
console.log(result);
es6后
let str = `
- 沈腾
-
- 马丽
-
- 魏翔
-
- 艾伦
-
`
//变量拼接
let lovest = '魏翔';
let out = `${lovest}是我心目中最搞笑的演员!!`
ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
let name = '尚硅谷';
let change = function(){
console.log('我们可以改变你!!');
}
const school = {
name,
change
//方法的简化
improve(){
console.log('我们可以提高你的技能')
}
}
let fn = function(){
};
let fn = (形参) =>{
函数体
}
function getName(){
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置window对象的name属性
window.name = '北京大学';
const school = {
name:'beijindaxue';
}
//直接调用
getName(); //北京大学
getName2(); //北京大学
//call方法调用(可以改变函数内部this)
getName.call(school); //beijindaxue
getName2.call(school); //北京大学
//箭头函数的this值是静态的,始终指向函数在声明时所在作用域下的this的值
let Person = (name,age){
this.name = name;
this.age = age;
}
let me = new Person('xiao',30);
console.log(me);//会报错,Person不是一个构造器
...rest
参数代替(但如果箭头函数的 this如果指向普通函数,它的 argumens 继承于该普通函数)let fn = () => {
console.log(arguments);
}
fn(1,2,3);//报错,arguments没有定义
fun()
let fun = ()=>{
console.log('测试一下!')
}
let a = () =>{};
console.log(a.prototype); // undefined
如果没有特殊指向,setInterval和setTimeout的回调函数中this的指向都是window。这是因为JS的定时器方法是定义在window下的
具有默认值的参数,一般位置要靠后(潜规则)
如果不传c这个参数,且不给c赋初始值,c就是NaN。
function add(a,b,c){
return a + b + c;
}
let result = add(1,2);
console.log(result);
function connect({host='127.0.0.1',username,password,post}){
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
connect({
host:'localhost',
username:'root',
password:'root',
port:3306
})
用于获取函数的实参,用来代替arguments
ES5获取实参的方式
function date(){
console.log(arguments);//得到类数组的对象
}
date('小明','小米','小白');
ES6后使用rest参数
function date(...args){
console.log(args);//得到一个数组
}
date('小明','小米','小白');
扩展运算符能将【数组】转化为逗号分隔的【参数序列】
const boys = ['qq','ee','rr'];
function chunwan (){
console.log(arguments);
}
chunwan(boys);//arguments只有一个数组元素,等同于chuanwan(boys)
chuanwan(...boys);//arguments有三个元素;等同于chuanwan('qq','ee','rr')
rest参数是将其放在函数声明的形参位置上,而扩展运算符是放在函数调用的实参上
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
const zuixuanxiaopingguo = [...kuaizi,...fenghuang];
console.log(zuixuanxiaopingguo);
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];
console.log(sanyecao);
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值,是一种类似于字符串的数据类型
let s = Symbol();
let result1 = s + 100;//报错
let result2 = s + s;//报错
//通过函数创建
let s = Symbol();
console.log(s,typeof s);//Symbol() 'symbol'
//通过函数创建并传入字符串
let s2 = Symbol('北京大学');
let s3 = Symbol('北京大学');
console.log(s2 === s3);//fasle;相当于两个人都叫张三,但是身份证号却不一样
//使用Symbol.for创建
let s4 = Symbol.for('北京大学');
let s5 = Symbol.for('北京大学');
console.log(s4,typeof s);//Symbol(北京大学) 'symbol'
console.log(s4 === s5)//true
使用Symbol.for创建可以通过描述字符串得到唯一的symbol值
给对象添加属性和方法,表示独一无二的。
以下这种方法也可以,但是有一定的风险,我们不知道game对象中有没有up,有没有down;所以需要判断,就增加了复杂度
let game = {};
game.up = function(){
}
使用symbol:安全,高效
let game = {};
//声明一个对象
let methods = {
up: Symbol(),
down: Symbol()
}
game[method.up] = function(){
console.log('我可以向上');
}
game[method.down] = function(){
console.log('我可以向下');
}
let youxi = {
name:'狼人杀',
[Symbol('say')]:function(){
console.log('我可以说话!');
},
[Symbol('zibao')]:function(){
console.log('我可以自爆!');
}
}
迭代器是一个接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口(js中Iterator接口其实就是对象的属性:symbol.iterator),都可以完成遍历操作。
const xiyouji = ['唐僧','孙悟空','猪八戒','沙僧'];
for(let v of xiyou){
console.log(v);//c,孙悟空,猪八戒,沙僧
}
for(let v of xiyou){
console.log(v);//0,1,2,3
}
console.log(xiyou)//原型上有symbol.iterator属性,值为一个函数
let iterator = xiyou[Symbol.iterator]();//xiyou[Symbol.iterator]对应的是一个函数
console.log(iterator)//iterator 原型上有一个next的方法
console.log(iterator.next());//第一次调用对象的next方法指针自行指向数据结构的第一个成员{value:'唐僧',done:false}
console.log(iterator.next());//{value:'孙悟空',done:false} done表示是否完成
console.log(iterator.next());//{value:'猪八戒',done:false}
console.log(iterator.next());//{value:'沙僧',done:false}
console.log(iterator.next());//{value:'undefined',done:true} done为真表示遍历已完成
生成器函数是ES6提供的一种异步编程解决方案,语法行为和传统函数不同
ES6之前:纯回调函数
function *gen(){
console.log('hello generator');
}
let iterstor = gen();
console.log(iterstor);//返回了一个迭代器对象gen{}
iterstor.next();//hello generator
function *ken(){
console.log(111);
yield '一只没有耳朵',
console.log(222);
yield '一只没有尾巴',
console.log(333);
yield '真奇怪';
console.log(444);
}
let iterstor2 = ken();
iterstor2.next();//111
console.log(iterstor2.next())//{value:'一只没有耳朵',done:false}
iterstor2.next();//222
console.log(iterstor2.next())//{value:'一只没有尾巴',done:false}
iterstor2.next();//333
console.log(iterstor2.next())//{value:'真奇怪',done:false}
iterstor2.next();//444
console.log(iterstor2.next())//{value:undefined,done:false}
function * gen(arg){
console.log(arg); //AAA
let one = yield 111;
console.log(one); //BBB
let two = yield 222;
console.log(two); //CCC
let three = yield 333;
console.log(three); //DDD
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());//{value:111,done:false}
//next方法可以传入实参
console.log(iterator.next('BBB'));// {value:222,done:false}
console.log(iterator.next('CCC'));// {value:333,done:false}
console.log(iterator.next('DDD'));// {value:undefined,done:true}
Promise是ES6引入的异步编程的解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
一个 Promise对象有以下三种状态:
Promise接受一个参数,该参数为一个函数类型的值,该函数有两个形参:resolve,reject。分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数;resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected
//实例化Promise对象
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('随便什么数据');
}, 2000);
});
console.log(p);
传入的是一个匿名函数,因此会立即执行。所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:
function runAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('随便什么数据');
}, 2000);
});
return p;
}
runAsync()
执行这个函数我们得到了一个Promise对象,这个对象上有then、catch方法。then 表示异步成功执行后的数据状态变为reslove ;catch 表示异步失败后执行的数据状态变为reject 。all表示把多个没有关系的Promise封装成一个Promise对象使用then返回一个数组数据
调用该对象的.then方法,then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法),将相应的回调函数放入微任务(microtask)中
runAsync().then(function(data){
console.log(data);//随便什么数据
});
因此,.then里面的函数就跟我们平时的回调函数是一个意思,能够在runAsync这个异步任务执行完成之后被执行。
下面是回调函数的写法:
function runAsync(callback){
setTimeout(function(){
console.log('执行完成');
callback('随便什么数据');
}, 2000);
}
runAsync(function(data){
console.log(data);
});
如果有多层回调,比如callback也是一个异步操作,而且执行完后也需要有相应的回调函数,这样就势必会造成回调地狱。
function runAsync1(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务1执行完成');
resolve('随便什么数据1');
}, 1000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务2执行完成');
resolve('随便什么数据2');
}, 2000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务3执行完成');
resolve('随便什么数据3');
}, 2000);
});
return p;
}
runAsync1()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return runAsync3();
})
.then(function(data){
console.log(data);
});
这样能够按顺序,每隔两秒输出每个异步回调中的内容,在runAsync2中传给resolve的数据,能在接下来的then方法中拿到。运行结果如下:
相对应的回调函数的写法:
function runAsync4(callback){
callback();
};
runAsync4(function(){
setTimeout(function(){
console.log('异步任务1执行完成');
console.log('随便什么数据1');
setTimeout(function(){
console.log('异步任务2执行完成');
console.log('随便什么数据2');
setTimeout(function(){
console.log('异步任务3执行完成');
console.log('随便什么数据3');
}, 2000);
}, 2000);
}, 2000);
})
reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调
getNumber函数用来异步获取一个数字,2秒后执行完成,如果数字小于等于5,我们认为是“成功”了,调用resolve修改Promise的状态。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因。
function getNumber(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
return p;
}
getNumber()
.then(
function(data){
console.log('resolved');
console.log(data);
},
function(reason, data){
console.log('rejected');
console.log(reason);
}
);
它和then的第二个参数一样,用来指定reject的回调,用法是这样:
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。请看下面的代码:
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
console.log(somedata); //此处的somedata未定义
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
在resolve的回调中,我们console.log(somedata);而somedata这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了。但是在这里,会得到这样的结果:
也就是说进到catch方法里面去了,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句有相同的功能。
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
用Promise.all来执行,all接收一个数组参数,里面的值最终都返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面。那么,三个异步操作返回的数据哪里去了呢?都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。所以上面代码的输出结果就是
有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据
all方法的效果实际上是谁跑的慢,以谁为准执行回调,那么race方法谁跑的快,以谁为准执行回调;我们把上面runAsync1的延时改为1秒来看一下
Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
1秒后runAsync1已经执行完了,此时then里面的就执行了
在then里面的回调开始执行时,runAsync2()和runAsync3()并没有停止,仍旧再执行。于是再过1秒后,输出了他们结束的标志。
用race给某个异步请求设置超时时间,并且在超时后执行相应的操作
//请求某个图片资源
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'xxxxxx';
});
return p;
}
//延时函数,用于给请求计时
function timeout(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('图片请求超时');
}, 5000);
});
return p;
}
Promise
.race([requestImg(), timeout()])
.then(function(results){
console.log(results);
})
.catch(function(reason){
console.log(reason);
});
requestImg函数会异步请求一张图片,我把地址写为"xxxxxx",所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。运行结果如下:
//1.引入fs模块
const fs = require('fs');
// //2.调用方法读取文件
// fs.readFile('./为学',(err,data) =>{
// //如果失败,则抛出错误
// if(err) throw err;
// //如果没有出错,则输出内容
// console.log(data.toString());
// });
//使用Promise封装
const p = new Promise(function (resolve, reject) {
fs.readFile('./为学',(err,data)=>{
//如果失败就不能像上面一样抛出错误了,而是要改变Promise对象的一个状态,调用reject(err),
// 通过调用reject,可以改变他的状态为失败,并且他失败的值是err这个错误对象
if(err) reject(err)
//如果成功,调用resolve,修改Promise的状态为成功,往里传参可以设置他成功的值
resolve(data);
})
})
p.then(function (value) {
console.log(value.toString());
},function (reason) {
console.log('读取失败');
})
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
reject('出错啦');
},1000)
})
const result = p.then((value) => {
console.log(value);
},reason=>{console.warn(reason);
})
console.log(result);
先打印出console.log(result);
一个Promise对象,再打印出console.warn(reason);
出错啦,不仅仅因为1s的延迟,更是因为异步调用,浏览器主线程不会阻塞
上述代码可以.then方法返回一个promise对象,但是这个promise的状态是由回调函数的执行结果来决定的
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
resolve('用户数据');
},1000)
})
const result = p.then((value) => {
console.log(value);//用户数据
return 123;//返回的是一个非promise类型的数据
},reason=>{console.warn(reason);
})
console.log(result);//promise对象
result为一个promise对象,并且点开后状态为成功[[PromiseStatus]]:'fulfilled'
;返回值为对象的成功值[[PromiseValue]]:123
如果没有return 123 ,没有return,默认返回结果为undefined,undefined并不是一个Promise对象,因此点开后状态为成功[[PromiseStatus]]:'fulfilled'
;返回值为对象的成功值[[PromiseValue]]:undefined
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
resolve('用户数据');
},1000)
})
const result = p.then((value) => {
console.log(value);//用户数据
return new Promise((resolve,reject)=>{
resolve('ok');
});//返回的是一个promise类型的数据
},reason=>{console.warn(reason);
})
console.log(result);//promise对象
result作为Promise对象,由于内部返回的是resolve,点开后状态为成功[[PromiseStatus]]:'fulfilled'
值为[[PromiseValue]]:ok
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
resolve('用户数据');
},1000)
})
const result = p.then((value) => {
console.log(value);//用户数据
return new Promise((resolve,reject)=>{
reject('error');
});//返回的是一个promise类型的数据
},reason=>{console.warn(reason);
})
console.log(result);//promise对象
result作为Promise对象,由于内部返回的是reject,点开后状态为成功[[PromiseStatus]]:'rejected'
值为[[PromiseValue]]:error
const p = new Promise((resolve,reject) => {
setTimeout(()=>{
resolve('用户数据');
},1000)
})
const result = p.then((value) => {
console.log(value);//用户数据
throw '出错啦!';
},reason=>{console.warn(reason);
})
console.log(result);//promise对象
点开后状态为成功[[PromiseStatus]]:'rejected'
值为[[PromiseValue]]:出错啦!
const p = new Promise((resolve,reject)=>{
// 1.创建对象
const xhr = new XMLHttpRequest();
// 2.初始化
//发 GET类型的请求 给这个接口发请求https://api.apiopen.top/getJoke
xhr.open("GET","https://api.apiopen.top/getJoke");
// 3.发送
xhr.send();
// 4.绑定事件,处理响应结果
xhr.onreadystatechange=function(){
// 对状态做出一个判断
if(xhr.readyState===4){
// 判断响应状态码 200-300 2系列的响应状态码都为成功
if(xhr.status >= 200 && xhr.status <= 300){
// 表示成功 resolve修改promise的状态
resolve(xhr.response);
}else{
// 如果失败
reject(xhr.status);
}
}
}
})
// 指定回调 结构清晰
p.then(function(value){
// 如果成功打印value
console.log(value);
},function(reason){
console.log(reason);
})
p.then(value=>{},reason=>{}).then(value=>{},reason=>{})
then方法在指定回调的时候是可以只指定一个的
p.then(value=>{}).then(vale=>{})
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator
接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,集合的属性和方法:
let s = new Set();
console.log(s,typeof s); //类型为object
let s2 = new Set(['大事儿','小事儿','好事儿','坏事儿','小事儿')];
console.log(s2);//自动去重['大事儿','小事儿','好事儿','坏事儿',]
//元素个数
console.log(s2.size);
//添加新的元素
s2.add('喜事儿');
console.log(s2)//('大事儿','小事儿','好事儿','坏事儿','小事儿','喜事儿');
//删除元素
s2.delete('坏事儿');
console.log(s2)//('大事儿','小事儿','好事儿','小事儿','喜事儿');
//检测
console.log(s2.has('糟心事'))//false
//清空
sw.clear();
console.log(s2)//{}
//使用for of遍历
for(let v of s2){
console.log(v);
}
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类
型的值(包括对象)都可以当作键。Map 也实现了iterator 接口,所以可以使用『扩展运算符』和
『for…of…』进行遍历;
// Map集合
// 创建一个空 map
let m = new Map();
// 添加元素一
m.set('name','北京大学');
m.set('change',function(){console.log('我们可以改变你!')})
console.log(m);
//添加元素二:键为对象,值为数组
let key = {
country:'中国'
};
m.set(key,['北京','上海','深圳']);
console.log(m);
//size:元素个数
console.log(m.size);//3
//delete 删除元素
m.delete('name');
//获取
console.log(m.get('change'));//function(){console.log('我们可以改变你!')};
console.log(m.get(key))//['北京','上海','深圳']
//清空
m.clear();
//遍历
for(let v of m){
console.log(v);
}
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键
字,可以定义类。基本上,ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做
到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已;
ES6之前实例化对象
//手机
function Phone (brand,price){
this.brand = brand;
this.price = price;
}
//添加方法
Phone.prototype.call = function() {
console.log('我可以打电话!');
}
//实例化对象
let Huawei = new Phone('华为',5999);
Huawei.call();
console.log(Huawei);
ES6之后通过类名来实例化对象
class Phone{
//构造方法,名字不能修改
constructor(brand,price){
this.brand = brand;
this.price = price;
}
call(){
console.log('我可以打电话!');
}
}
let onePlus = new Phone('1+',1999);
console.log(onePlus);
function Phone(){
}
//构造函数本身也是一个对象,因此是可以往这个对象上面添加属性和方法
Phone.name = '手机';
Phone.change = function(){
console.log('我可以改变世界');
}
//实例对象
let nokia = new Phone();
console.log(nokia.name)//undefined
nokia.change();//报错
从上述例子中可以看出实例对象是没有构造函数对象上的属性,也没有构造函数上的方法.因此函数对象是函数对象,实例对象是实例对象
那么,实例对象上的属性跟什么是相同的呢?
实例对象上的属性跟构造函数上的原型对象是相同的。
function Phone(){
}
//构造函数本身也是一个对象,因此是可以往这个对象上面添加属性和方法
Phone.name = '手机';
Phone.change = function(){
console.log('我可以改变世界');
}
Phone.prototype.size = '5.5inch';
let nokia = new Phone();
console.log(nokie.size);//5.5inch
上面中的name,change属于构造函数这个对象.并不属于实例对象。在面向对象中这样的属性就称为 静态属性
而类似的在类中,某些属性属于类而不属于实例对象就称为class的静态成员。
class Phone{
static name = '手机';
static change(){
console.log('我可以改变这个世界');
}
}
let nokie = new Phone();
console.log(nokia.name);//undefined
console.log(Phone.name);//手机
ES5中使用构造函数继承
function Phone (brand,price){
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function() {
console.log('我可以打电话!');
}
//智能手机
function SmartPhone(brand, price, color, size){
//改变this值,此时this指向SmartPhone的实例
Phone.call(this,brand,price);
this.color = color;
this.size = size;
}
//设置子集构造函数的原型:这样子级的实例对象就会有父级的方法
SmartPhone.prototype = new Phone;
//做一个矫正,不写也可
SmartPhone.prototype.constructor = SmartPhone;
//声明子类的方法
SmartPhone.prototype.photo = function(){
console.log('我可以拍照');
}
SmartPhone.prototype.playGame= function(){
console.log('我可以玩游戏');
}
const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch')
console.log(chuizi)
ES6类的继承
class Phone{
constructor(brand,price){
this.brand = brand;
this.price = price;
}
//父类的成员属性
call(){
console.log('我可以打电话!!');
}
};
class SmartPhone extends Phone {
//构造方法
constructor(brand,price,color,size){
supper(brand,price);
this.color = color;
this.size = size;
}
phone(){
console.log('拍照');
}
playGame(){
console.log('玩游戏');
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
console.log(xiaomi);
在子类中声明一个同父类同名的方法,即重写
class Phone{
constructor(brand,price){
this.brand = brand;
this.price = price;
}
//父类的成员属性
call(){
console.log('我可以打电话!!');
}
};
class SmartPhone extends Phone {
//构造方法
constructor(brand,price,color,size){
supper(brand,price);
this.color = color;
this.size = size;
}
phone(){
console.log('拍照');
}
playGame(){
console.log('玩游戏');
}
call(){
console.log('我可以进行视频通话')
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
console.log(xiaomi);
xiaomi.call();
这个时候子类是不可以调用父类的同名call方法
var p={
_age:18,
get age(){ //Getter不能有任何形式的参数
return this._age;
},
set age(val){ //Setter必须恰好有一个形式参数
console.log(val);
this._age=val;
}
}
p.age; // 18
p.age=20; // 20
p.age; // 20
class Phone{
get price(){
console.log('价格属性被读取了');
return 'iloveyou'//返回值就是price这个属性的值
}
}
let s = new Phone();
console.log(s.price)//价格属性被读取了 iloveyou
如果不写get
class Phone{
price(){
console.log('价格属性被读取了');
return 'iloveyou'
}
}
let s = new Phone();
console.log(s.price)
输出的是price这个函数
price(){
console.log('价格属性被读取了');
return 'iloveyou'//返回值就是price这个属性的值
}
set:对属性进行赋值
class Phone{
get price(){
console.log('价格属性被读取了');
return 'iloveyou'//返回值就是price这个属性的值
}
//使用set必须有一个参数
set price(newVal){
console.log('价格属性被修改了');
console.log(newVal);//free
}
}
let s = new Phone();
s.price //iloveyou
s.price = 'free'//价格属性被修改了
ES6 新增了一些 Object 对象的方法:
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来;
模块化的优势有以下几点:
ES6 之前的模块化规范有:
模块功能主要由两个命令构成:export 和 import;