# HTML+CSS+JS **Repository Path**: SeteVII/html-css-js ## Basic Information - **Project Name**: HTML+CSS+JS - **Description**: html+css+js - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-10-11 - **Last Updated**: 2023-10-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # HTML+CSS ## 水平垂直居中 ### flex弹性布局 ```css .father { display: flex; align-items: center; /* 垂直居中 */ justify-content: center; /* 水平居中 */ } .son{ ... } ``` ### absolute+margin:auto ```css .father { position: relative; } .son { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; } ``` ### absoulte+transform ```css .father { position: relative; } .son { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } ``` ### grid布局 ```css .father { display: grid; align-items: center; justify-content: center; width: 200px; height: 200px; border: 1px solid; } ``` ### table-cell ```css .father { display: table-cell; vertical-align: middle; text-align: center; } .son { display: inline-block; } ``` ## BFC BFC:块格式化上下文,是一块独立的渲染区域,内部元素不会影响外部元素。 **创建BFC的条件** - 根元素:body - 元素设置浮动:float除none以外的值 - 元素设置绝对定位:position(absolute、fixed) - display:inline-block、table-cell、flex等 - overflow:hidden、auto、scroll **BFC特点** - 垂直方向上,自上而下的排列,和文档流的排列方式一致 - 在BFC中上下相邻的两个容器的margin会重叠 - 计算BFC的高度时,需要计算浮动元素的高度 - BFC区域不会与浮动的容器发生重叠 - BFC是独立的容器,容器内部的元素不会影响外部元素 - 每个元素的左margin值和容器的左border相接触 **BFC的作用** - **解决margin的重叠问题**:由于BFC是一个独立的区域,内部的元素和外部的元素互不影响,将两个元素变为两个BFC,就解决了margin重叠的问题 - **解决高度塌陷的问题**:在子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为0。解决这个问题,只需要把父元素变成一个BFC。常用的办法给父元素设置`overflow:hidden` - **创建自适应两栏布局**:左边宽度固定,右边宽度自适应 ```html
``` ```css .left { width: 100px; height: 200px; background: salmon; float: left; } .right { height: 300px; background: seagreen; overflow: hidden; } ``` # js基础 ## js输出 ```js // 控制浏览器弹出一个警告窗 alert('123'); // 输出内容到页面上 document.write('345'); // 输出内容到控制台 console.log('456'); ``` ## js事件 ```html 点击链接 点击链接 ``` # 强制类型转换 强制类型转换 指将一个数据类型强制转换为其他的数据类型 类型转换主要指,将其他的数据类型,转换为String Boolean Number 将其他的数据类型转换为String 方式一: - 调用被转类型的toString()方法 - 该方法不会影响到原变量的值,它会将转换的结果返回 - null和undefined没有toString()方法 方式二: - 使用String()函数 - 使用String()函数做强制转换时, 对于Number和Boolean实际上就是调用的toString()方法 对于null和undefined,就不会调用toString()方法.它会将null转换为'null',将undefined转换为'undefined' # 数据类型检测 ## typeof typeof可以区分object和function 数组(日期/正则)、对象、null会被判断为object(null是因为null的二进制全为0,000开头的是对象) ```js console.log(typeof 2); //number console.log(typeof true); //boolean console.log(typeof 'str'); //string console.log(typeof []); //object console.log(typeof function () { }); //function console.log(typeof {}); //object console.log(typeof undefined); //undefined console.log(typeof null); //object ``` ## instanceof instanceof判断对象的类型,只能判断引用数据类型,用来测试一个对象在其原型链中是否存在一个构造函数prototype属性 内部运行机制:判断在其原型链中能否找到该类型的原型 功能:判断两个对象是否属于实例关系 缺点:无法判断某一对象具体属于哪种类型 ```javascript console.log(2 instanceof Number); //false console.log(true instanceof Boolean); //false console.log('str' instanceof String); //false console.log([] instanceof Array); //true console.log(function () { } instanceof Function); //true console.log({} instanceof Object); //true ``` 如果`instanceof`想要检测基本数据类型,可`new`一个包装类型 ```javascript const num1=new Number(123); console.log(num1 instanceof Number);//true console.log(num1 instanceof Object);//true const str1=new String("abcdef"); console.log(str1 instanceof String);//true console.log(num1 instanceof Object);//true ``` ## constructor 功能:`constructor`是原型`prototype`的一个属性,可以通过一个对象的`constructor`属性比对对象的数据类型 缺点:`null`和`undefined`没有`constructor` > 作用:1.判断数据的类型 2.对象实例通过constructor对象访问它的构造函数 ```js console.log((2).constructor === Number); //true console.log((true).constructor === Boolean); //true console.log(('str').constructor === String); //true console.log(([]).constructor === Array); //true console.log((function () { }).constructor === Function); //true console.log(({}).constructor === Object); //true ``` 如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了 ```js function Fn() { } Fn.prototype = new Array() var f1 = new Fn() console.log(f1.constructor === Fn); //false console.log(f1.constructor === Array); //true ``` ## Object.prototype.toString.call toString()是Object的原型方法,调用该方法,默认返回当前对象的[[Class]] **obj.toString()** Object自带方法,用于将对象转换为字符串 undefined、null对象没有toString方法 ```js //Number const num = 123; console.log(num.toString()); // '123' console.log((123).toString()); // '123'整数必须赋值给变量后或放在括号中再调用toString console.log(1.23.toString()); // '1.23'小数可直接调用 console.log(NaN.toString()); // 'NaN' console.log(Infinity.toString()); // 'Infinity' console.log(-Infinity.toString()); // -Infinity根据运算符优先级关系,先执行toString再将String转为Number //数字通过toString进行进制转换 console.log(num.toString()); // '123'默认转为十进制 console.log(num.toString(2)); // '1111011' console.log(num.toString(8)); // '173' console.log(num.toString(16)); // '7b' //Array console.log([1, 2, 3].toString()); // '1,2,3'结果与数组的join()方法相同 //Object console.log(({}).toString()); // "[object Object]" //Function const func = function () { }; console.log(func.toString()); // "function(){}" //Boolean const t = true, f = false; console.log(t.toString()); // 'true'返回对应字符串 console.log(f.toString()); // 'false' ``` **Object.prototype.toString.call()** 使用Object对象的原型方法toString来判断数据类型 ```js var a = Object.prototype.toString console.log(a.call(2)); //[object Number] console.log(a.call(true)); //[object Boolean] console.log(a.call('str')); //[object String] console.log(a.call([])); //[object Array] console.log(a.call(function () { })); //[object Function] console.log(a.call({})); //[object Object] console.log(a.call(undefined)); //[object Undefined] console.log(a.call(null)); //[object Null] ``` > 同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,为什么? > > 因为toString是Obejct的原型方法,而Array、function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的*toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object原型上的toString方法。 # 运算符 运算符也叫操作符 通过运算符可以对一个或多个值进行计算,并获取运算结果 ## typeof typeof 就是一个运算符,可以用来获取一个值的类型,它会将该值的类型以字符串的形式返回 ## 算数运算符 + - * / % 任何值和NaN做加法计算结果都是NaN 任何值 + '' 即可转换为String,调用String()函数,隐式转换 任何值做 - / * 运算时都会自动转换为Number,我们可以通过 -0 *1 /1 来将其转换为Number,隐式转换 ## 逻辑运算符 &&与 ||或 !非 !非. 取反Boolean值,如果对一个非布尔值进行元素,则会将其转化为布尔值,然后再取反.利用该特点,可以将其他数据类型转换为布尔值。!!!为任意数据类型取两次非运算(一次反结果错误),来将其转换为布尔值。原理和Boolean()函数一样。 &&与。对符号两侧的值进行运算并返回结果。运算规则:两个值都为true则为true,否则为false。短路,如果第一个值为false,不会检查第二个值。 ||或。对符号两侧的值进行运算并返回结果。运算规则:两个值都为false则返回false,否则为true。短路。如果第一个值为true,则不会检查第二个值。 (&& || )非布尔值的情况: 对于非布尔值进行与或运算时,会先将其转换为布尔值,然后再运算,并且返回 值。 与运算:如果两个值都为true,则返回第二个的值。如果两个值都为false,则返 第一个值。如果一个true,一个false,则返回false的值。 或运算:如果两个值都为false,则返回第二个的值。如果两个值都为true,则返 第一个值。如果一个true,一个false,则返回true的值。 ## 关系运算符 > < = >= <= 非数值情况: 非数值进行比较时,会将其转换为数字然后再比较,任何值和NaN比较都为false 符号两侧都为字符串时,不会转换为数字进行比较,分别比较字符串中字符的Unicode编码 # 函数节流 在规定的时间范围内相同的操作触发多次只执行一次 ```javascript export const debounce = (fn, delay) => { let timer = null return function () { let context = this, args = arguments clearTimeout(timer) timer = setTimeout(() => { fn.apply(context, args) timer = null }, delay); } } ``` # 函数防抖 事件被触发n秒后再回调,如果在n内又被触发了,则重新计时 ```javascript export default throttle = (fn, delay = 100) => { let timer = null let preTime = Date.now().getTime() return function () { let context = this, args = arguments, nowTime = Date.now().getTime() clearTimeout(timer) if (nowTime - preTime >= delay) { fn.apply(context, args) preTime = nowTime } else { timer = setTimeout(() => { fn.apply(context, args) timer = null }, delay); } } } ``` # let 1.变量不能重复声明 2.块级作用域 3.不存在变量提升 4.不影响作用域链 # const 1.一定要赋初始值 2.一般常量使用大写 3.常量的值不能修改 4.块级作用域 5.对于数组和对象的元素的修改,不算做对常量的修改,不会报错(常量地址没有发生改变,所以不会报错) # 解构赋值 ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值 ```js // 数组的解构(不常用) const COLOR = ['red', 'green', 'yellow', 'blue']; let [red, green, yellow, blue] = COLOR; console.log(red); // red console.log(green); // green console.log(yellow); // yellow console.log(blue); // blue // 对象的解构(常用) // 方法频繁调用,使用对象的解构赋值 const PERSON = { name: 'luck', age: 16, sayName: function () { console.log(PERSON.name); } } let { name, age, sayName } = PERSON; console.log(name); //luck console.log(age); //16 console.log(sayName); //ƒ () {console.log(this.name);} sayName(); //luck ``` # 模板字符串 引入新的声明字符串的方式[``] '' "" ```js // 1.声明 let str1 = `我也是一个字符串嗷`; console.log(str1, typeof str1); //我也是一个字符串嗷 string // 2.内容中可以直接出现换行符 let str2 = ``; console.log(str2); {/* */} // 3.变量拼接 let color = 'red'; let colorEst = `${color}是鲜艳的`; console.log(colorEst); //red是鲜艳的 ``` # 简化对象写法 ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法 ```js let name = 'luck'; let change = function () { console.log('luck是可爱的小狗'); } const animal = { name, change, improve() { console.log('小狗'); } } console.log(animal); //{name: 'luck', change: ƒ, improve: ƒ} // 原写法 // const animal = { // name: name, // change: change, // improve: function () { // } // } ``` # 箭头函数 ES6允许使用箭头定义函数 箭头函数适合与this无关的回调,如定时器,数组的方法回调 箭头函数不适合与this有关的回调,如dom事件回调,对象的方法 ```js // 声明一个函数 let fn1 = function () {} let fn2 = (a, b) => { return a + b } let result = fn2(1, 2) console.log(result); //3 // 1.this是静态的,this始终指向函数声明时所在作用域下的this值 function getName() { console.log(this.name); } let getName2 = () => { console.log(this.name); } // 设置window的对象name属性 window.name = 'luck'; const school = { name: 'school', } // 直接调用 // 普通函数直接调用this指向window // 箭头函数在全局作用域下声明的,this指向window getName(); //luck getName2(); //luck // call方法调用 // 箭头函数this值是静态的,this始终指向函数在声明对象的this值 getName.call(school); //school getName2.call(school); //luck // 2.不能作为构造函数实例化对象 let Person = (name, age) => { this.name = name; this.age = age; } // let me = new Person('七', 23); // console.log(me); //Person is not a constructor // 3.不能使用arguments变量 // let fn3 = () => { // console.log(arguments); //arguments is not defined // } // fn3(124) // 4.箭头函数简写 // 1)省略小括号,当形参有且仅有一个 // 2)省略花括号,当代码体只有一条语句的时候,return必须省略,语句的执行结果就是函数的返回值 let pow = (n) => n * n; console.log(pow(1)); //1 ``` # 参数默认值 ES6允许给函数参数赋值初始值 ```js // 1.形参的初始值,具有默认值的参数,一般位置要靠后 function add(a, b, c = 0) { return a + b + c } let result = add(1, 2); console.log(result); //3 // 2.与解构赋值结合 function connect({ host = '127.0.0.1', username, password, port }) { console.log(host); // 127.0.0.1 console.log(username); //root console.log(password); //root console.log(port); //3000 } connect({ // host: '', username: 'root', password: 'root', port: 3000, }) ``` # rest参数 ES6引入rest参数,用来获取函数的实参,用来代替arguments ```js // ES5获取实参的方法(伪数组对象) function date() { console.log(arguments); } date('111', '222') //['111',,'222' callee: ƒ, Symbol(Symbol.iterator): ƒ] ``` ```js // rest参数(数组) function date(...args) { console.log(args); } date('111', '222'); //['111', '222'] // rest参数必须放在参数的最后面 function fn(a, b, ...args) { console.log(a); //1 console.log(b); //2 console.log(...args); //3 4 5 6 } fn(1, 2, 3, 4, 5, 6); ``` # 扩展运算符 [...] 扩展运算符能将[数组]转换为逗号分隔的[参数序列] ```js // 声明一个数组 const color = ['red', 'green', 'blue']; // 声明一个函数 function colors() { console.log(arguments); } colors(color); // [Array(3), callee: ƒ, Symbol(Symbol.iterator): ƒ] 1个实参 colors(...color) //['red', 'green', 'blue', callee: ƒ, Symbol(Symbol.iterator): ƒ] 3个实参 ``` # 扩展运算符的应用 ```js // 1.数组的合并 const color = ['red', 'green', 'blue']; const num = ['1', '2', '3']; const cononect = color.concat(num); console.log(cononect); //['red', 'green', 'blue', '1', '2', '3'] const connect = [...color, ...num]; console.log(connect); //['red', 'green', 'blue', '1', '2', '3'] // 2.数组的克隆 const colors = ['red', 'green', 'blue']; const clone = [...color]; console.log(clone); //['red', 'green', 'blue'] // 3.将伪数组转为真正的数组 const divs = document.querySelectorAll('div'); console.log(divs); //NodeList(3) [div, div, div] Object console.log([...divs]); //[div, div, div] Array ``` # Symbol ```js // 创建symbol let s = Symbol(); console.log(s, typeof s); //Symbol() 'symbol' let s2 = Symbol('seven'); console.log(s2); //Symbol(seven) let s3 = Symbol('seven'); console.log(s2 == s3); //fasle // Symbol.for创建 let s4 = Symbol.for('seven'); console.log(s4, typeof s4); //Symbol(seven) 'symbol' // 不能与其他数据进行运算 // let result = s + 100; //Cannot convert a Symbol value to a number // let result = s + '100'; //Cannot convert a Symbol value to a string ``` # Symbol创建对象属性 ```js // 向对象中添加方法 let game = { name: '闪耀暖暖', } // 声明一个对象 let methods = { up: Symbol(), down: Symbol(), } game[methods.up] = function () { console.log('向上'); } game[methods.down] = function () { console.log('向下'); } console.log(game); //{name: '闪耀暖暖', Symbol(): ƒ, Symbol(): ƒ} let youxi = { name: '狼人杀', [Symbol('say')]: function () { console.log('我可以发言'); } } console.log(youxi); //{name: '狼人杀', Symbol(say): ƒ} ``` # 迭代器 Iteartor 是一种接口(对象的一个属性),为各种不同的数据结构提供统一的访问机制 遍历操作 ```js // 声明一个数组 let color = ['green', 'blue', 'red', 'yellow']; // 使用for...of遍历数组 for (let v of color) { // green // blue // red // yellow console.log(v); } // 创建一个指针对象,指向当前数据结构的起始位置 // 第一次调用对象的next方法,指针自动指向数据结构的第一个成员 // 接下来不断调用next方法,指针一直往后移动移动,直到只想最后一个成员 // 每调用next方法返回一个包含value和done属性的对象 console.log(color); //Symbol(Symbol.iterator): ƒ values() let iterator = color[Symbol.iterator](); console.log(iterator); //Array Iterator {} next: ƒ next() console.log(iterator.next()); //{value: 'green', done: false} console.log(iterator.next()); //{value: 'blue', done: false} console.log(iterator.next()); //{value: 'red', done: false} console.log(iterator.next()); //{value: 'yellow', done: false} console.log(iterator.next()); //{value: 'undefined', done: true} ``` # 生成器函数 生成器就是一个特殊的函数 异步编程 纯回调函数 node fs ajax mongodb 生成器是对异步编程的一个解决方案 ```js // function* gen() { // console.log('hello generator'); // } // let iterator = gen(); // console.log(iterator); //gen {} // 调用next()方法运行 // iterator.next(); //hello generator // yield函数代码的分隔符 function* gen() { yield '一直没有耳朵'; yield '一直没有眼睛'; // console.log(333); yield '真奇怪'; // console.log(444); } let iterator = gen(); console.log(iterator); //gen {} console.log(iterator.next()); //{value: '一直没有耳朵', done: false} console.log(iterator.next()); //{value: '一直没有眼睛', done: false} console.log(iterator.next()); //{value: '真奇怪', done: false} console.log(iterator.next()); //{value: 'undefined', done: true} // 遍历 // for (let v of gen()) { // // 一直没有耳朵 // // 一直没有眼 // // 真奇怪 // console.log(v); // } ``` # 生成器函数参数 ```js function* gen(arg) { console.log(arg); //aaa let one = yield 1; console.log(one); //BBB let two = yield 2; console.log(two); //CCC let three = yield 3; console.log(three); //DDD let four = yield 4; console.log(four); //EEE } let iterator = gen('aaa'); //传给arg // ?next方法可以传入实参,这个实参就是整个yield语句的返回结果 console.log(iterator.next('AAA')); console.log(iterator.next('BBB')); //传给第一个yield console.log(iterator.next('CCC')); //传给第二个yield console.log(iterator.next('DDD')); //传给第三个yield console.log(iterator.next('EEE')); //传给第四个yield ``` # Promise promise是ES6引入的异步编程的新解决方案, Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果 ```js // 实例化Promise对象 const p = new Promise((resolve, reject) => { setTimeout(() => { // let data = '数据库中的用户数据' // #resolve 成功 // resolve(data) let err = '数据读取失败'; // #reject 失败 reject(err) }, 1000); }) // 调用promise对象的then方法 p.then(value => { //#成功 console.log(value); //数据库中的用户数据 }, reason => { //#失败 console.log(reason); //数据读取失败 }) ``` # Promise的then方法 ```js const p = new Promise((resolve, reject) => { setTimeout(() => { resolve('用户数据'); }, 1000); }); // 调用then方法 then方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定 // 1.如果回调函数中返回的结果是非Promise类型的属性,状态为成功,返回值为对象成功的值 const result = p.then(value => { console.log(value); //用户数据 // 非Promise类型的属性 // return 'wer'; //: "fulfilled" : "wer" // 是Promise对象 // return new Promise((resolve, reject) => { // resolve('ok') //: "fulfilled" < value >: "ok" // }) // 抛出错误 throw '出错啦'; //: "rejected" : "出错啦" }, reason => { console.log(reason); }) console.log(result); // 链式调用 // p.then() ``` # Promise读取文件 ```js const { rejects } = require('assert'); const fs = require('fs'); // 调用方法读取文件 // fs.readFile('README.md', (err, data) => { // if (err) throw err; // console.log(data); // console.log(data.toString()); // }); // 使用promise封装 const p = new Promise((resolve, reject) => { fs.readFile('README.md', (err, data) => { if (err) reject(err); //失败 resolve(data); //成功 }) }); p.then(value => { console.log(value.toString()); }, reason => { console.log(reason); }) // 失败的回调 // p.catch(reason => { // console.log(reason); // }) ``` # Promise封装ajax ```js // 接口地址:https://api.apiopen.top/getJoke // 1.创建对象 const p = new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open('GET', "https://api.apiopen.top/getJoke"); xhr.send(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { if (xhr.status >= 200 & xhr.status < 300) { resolve(xhr.response); } else { reject(xhr.status); } } } }) p.then(value => { console.log(value); }, reason => { console.log(reason); }) ``` # 集合 ES6提供的新的数据结构 Set 类似于数组,但成员的值都是唯一的,集合实现了iterator接口, 可以使用扩展运算符和for...of进行遍历 ```js // 声明一个set let s = new Set(); let s2 = new Set(['大事', '小事', '好事', '小事']); console.log(s, typeof s); //Set [] object console.log(s2); // Set(3) [ "大事", "小事", "好事" ] // 元素个数 console.log(s2.size); //3 // 添加新的元素 s2.add('喜事') console.log(s2); // Set(4) [ "大事", "小事", "好事", "喜事" ] // 删除元素 s2.delete('喜事'); console.log(s2); //Set(3) [ "大事", "小事", "好事" ] // 检测 console.log(s2.has('好事')); //true // 清空 // s2.clear(); // console.log(s2); //Set [] // 遍历 for (const item of s2) { // 大事 // 小事 // 好事 console.log(item); } ``` # Map ES6提供的新的数据结构 Map 类似于对象,也是键值对的集合,但是键的范围不包括字符串,合作类型的值包括对象都可以当做键,集合实现了iterator接口, 可以使用扩展运算符和for...of进行遍历 ```js // 声明一个set let o = new Map(); // 添加元素 o.set('name', 'luck'); o.set('change', function () { console.log('我们可以改变你'); }) console.log(o, typeof o); //Map(2) {size: 2, name => luck, change => ƒ ()} object let key = { color: 'red' } o.set(key, ['北京', '上海']); console.log(o); //Map(3) {size: 3, name => luck, change => ƒ (), {color: 'red'} => (2) ['北京', '上海', …]} // 元素个数 console.log(o.size); //3 // 删除元素 o.delete('name'); console.log(o); //Map(2) {size: 2, change => ƒ (), {color: 'red'} => (2) ['北京', '上海', …]} // 读取 console.log(o.get('change')); //ƒ () {console.log('我们可以改变你');} // 清空 // o.clear(); // console.log(o); //Map(0) {size: 0} // 遍历 for (const item of o) { //['change', ƒ] ƒ () {\r\n console.log('我们可以改变你');\r\n} //['北京', '上海'] console.log(item); } ``` # Class ```js // ES5 function Phone(brand, price) { this.brand = brand; this.price = price; } // 添加方法 Phone.prototype.call = function () { console.log('我可以打电话'); } // 实例化对象 let huawei = new Phone('华为', 5888); huawei.call(); //我可以打电话 console.log(huawei); //Phone {brand: '华为', price: 5888} ``` ```js // 手机 // ES6 class Phone { // 构造方法 constructor constructor(brand, price) { this.brand = brand; this.price = price; } // 方法,必须写这种语法 call() { console.log('我可以打电话'); } } let huawei = new Phone('huawei', 8999); huawei.call() console.log(huawei); //Phone {brand: 'huawei', price: 8999} ``` # Class的静态成员 ```js // ES5 function Phone(){} Phone.name = '手机'; //静态成员 属于类不属于实例对象 Phone.change = function () { console.log('我可以听歌'); } Phone.prototype.size = '5.5inch' // debugger; let nokia = new Phone(); console.log(nokia.name); //undefined console.log(nokia.size); // nokia.change(); //发生异常: TypeError: nokia.change is not a function ``` ```js // ES6 // static 属于类不属于实例对象 class Phone { // 静态属性 static name = '手机'; static change() { console.log('我可以改变世界'); } } debugger; let nokia = new Phone(); console.log(Phone.name); //手机 console.log(nokia.name); //undefined Phone.change(); //我可以改变世界 ``` # Class的get和set ```js class Phone { get price() { console.log('价格属性被读取了'); return 'get读取' } // set必须有一个形参 set price(newVal) { console.log('价格属性被修改了'); } } let s = new Phone(); console.log(s.price); //价格属性被读取了 get读取 s.price = 3400; //价格属性被修改了 ``` # Class继承 ```js // ES5 // 手机 function Phone(brand, price) { this.brand = brand; this.price = price; } // 添加方法 Phone.prototype.call = function () { console.log('我可以打电话'); } // 智能手机 function SmarkPhone(brand, price, color, size) { Phone.call(this, brand, price); this.color = color; this.size = size; } // 设置子级构造函数的原型 SmarkPhone.prototype = new Phone; SmarkPhone.prototype.constructor = SmarkPhone; // 声明子类方法 SmarkPhone.prototype.photo = function () { console.log('我可以拍照'); } let huawei = new SmarkPhone('华为', 5888, 'black', '5.5inch'); console.log(huawei); //SmarkPhone {brand: '华为', price: 5888, color: 'black', size: '5.5inch'} ``` ```js // ES6 class Phone { constructor(brand, price) { this.brand = brand; this.price = price; } // 父类的成员属性 call() { console.log('我可以打电话'); } } class SmarkPhone extends Phone { constructor(brand, price, color, size) { super(brand, price); this.color = color; this.size = size; } photo() { console.log('我可以拍照'); } // 子类重写 call() { console.log('我可以视频通话'); } } let xiaomi = new SmarkPhone('小米', 7999, '玫瑰金', '5.5inch'); console.log(xiaomi); //SmarkPhone {brand: '小米', price: 7999, color: '玫瑰金', size: '5.5inch'} xiaomi.call(); //我可以视频通话 xiaomi.photo();//我可以拍照 ```